ZQuest Classic Coverage Report


Directory: src/
File: src/zq/zq_tiles.cpp
Date: 2025-05-29 08:39:38
Exec Total Coverage
Lines: 99 7679 1.3%
Functions: 1 200 0.5%
Branches: 14 6781 0.2%

Line Branch Exec Source
1 #include <cstring>
2 #include <cmath>
3
4 #include "base/files.h"
5 #include "base/qrs.h"
6 #include "base/dmap.h"
7 #include "base/cpool.h"
8 #include "base/autocombo.h"
9 #include "base/packfile.h"
10 #include "base/gui.h"
11 #include "base/combo.h"
12 #include "base/msgstr.h"
13 #include "base/zdefs.h"
14 #include "new_subscr.h"
15 #include "subscr.h"
16 #include "zq/zq_tiles.h"
17 #include "zq/zquest.h"
18 #include "tiles.h"
19 #include "zq/zq_misc.h"
20 #include "zq/zq_class.h"
21 #include "base/zsys.h"
22 #include "base/colors.h"
23 #include "base/qst.h"
24 #include "gui/jwin.h"
25 #include <base/new_menu.h>
26 #include "base/jwinfsel.h"
27 #include "hero_tiles.h"
28 #include "zq/questReport.h"
29 #include "dialog/info.h"
30 #include "dialog/scaletile.h"
31 #include "dialog/rotatetile.h"
32 #include "dialog/alert.h"
33 #include "drawing.h"
34 #include "colorname.h"
35 #include "zq/render.h"
36 #include "zinfo.h"
37 #include <fmt/format.h>
38 #include <functional>
39 #include "zq/moveinfo.h"
40 using std::set;
41
42
43 #ifdef _MSC_VER
44 #define stricmp _stricmp
45 #endif
46
47 #define HIDE_USED (show_only_unused_tiles&1)
48 #define HIDE_UNUSED (show_only_unused_tiles&2)
49 #define HIDE_BLANK (show_only_unused_tiles&4)
50 #define HIDE_8BIT_MARKER (show_only_unused_tiles&8)
51
52 extern void large_dialog(DIALOG *d);
53 static void massRecolorReset4Bit();
54 static void massRecolorReset8Bit();
55 static bool massRecolorSetup(int32_t cset);
56 static void massRecolorApply(int32_t tile);
57 extern int32_t last_droplist_sel;
58 extern int32_t TilePgCursorCol, CmbPgCursorCol;
59
60 int32_t ex=0;
61 int32_t nextcombo_fake_click=0;
62 int32_t invcol=0;
63 int32_t tthighlight = 1;
64 int32_t showcolortip = 1;
65 int32_t show_quartgrid = 0, hide_grid = 0;
66
67 tiledata *newundotilebuf;
68 std::vector<newcombo> undocombobuf;
69
70 BITMAP *selection_pattern;
71 byte selection_grid[18][18];
72 byte selection_anchor=0;
73
74 enum {selection_mode_normal, selection_mode_add, selection_mode_subtract, selection_mode_exclude};
75 BITMAP *selecting_pattern;
76 int32_t selecting_x1, selecting_x2, selecting_y1, selecting_y2;
77
78 extern int32_t bidcomboscripts_cnt;
79 extern script_struct bidcomboscripts[NUMSCRIPTSCOMBODATA];
80
81 BITMAP *intersection_pattern;
82
83 byte relational_template[48][4]=
84 {
85 { 0, 0, 0, 0 },
86 { 0, 1, 0, 0 },
87 { 1, 0, 0, 0 },
88 { 1, 1, 0, 0 },
89 { 0, 0, 1, 0 },
90 { 0, 1, 1, 0 },
91 { 1, 0, 1, 0 },
92 { 1, 1, 1, 0 },
93 { 0, 0, 0, 1 },
94 { 0, 1, 0, 1 },
95 { 1, 0, 0, 1 },
96 { 1, 1, 0, 1 },
97 { 0, 0, 1, 1 },
98 { 0, 1, 1, 1 },
99 { 1, 0, 1, 1 },
100 { 1, 1, 1, 1 },
101 { 0, 2, 0, 2 },
102 { 1, 2, 0, 2 },
103 { 0, 2, 1, 2 },
104 { 1, 2, 1, 2 },
105 { 3, 3, 0, 0 },
106 { 3, 3, 1, 0 },
107 { 3, 3, 0, 1 },
108 { 3, 3, 1, 1 },
109 { 3, 4, 0, 2 },
110 { 3, 4, 1, 2 },
111 { 2, 0, 2, 0 },
112 { 2, 1, 2, 0 },
113 { 2, 0, 2, 1 },
114 { 2, 1, 2, 1 },
115 { 2, 2, 2, 2 },
116 { 4, 3, 2, 0 },
117 { 4, 3, 2, 1 },
118 { 4, 4, 2, 2 },
119 { 0, 0, 3, 3 },
120 { 0, 1, 3, 3 },
121 { 1, 0, 3, 3 },
122 { 1, 1, 3, 3 },
123 { 0, 2, 3, 4 },
124 { 1, 2, 3, 4 },
125 { 3, 3, 3, 3 },
126 { 3, 4, 3, 4 },
127 { 2, 0, 4, 3 },
128 { 2, 1, 4, 3 },
129 { 2, 2, 4, 4 },
130 { 4, 3, 4, 3 },
131 { 4, 4, 4, 4 },
132 { 5, 5, 5, 5 }
133 };
134
135 byte dungeon_carving_template[96][4]=
136 {
137 { 0, 0, 0, 0 },
138 { 0, 1, 0, 0 },
139 { 1, 0, 0, 0 },
140 { 1, 1, 0, 0 },
141 { 0, 0, 1, 0 },
142 { 0, 1, 1, 0 },
143 { 1, 0, 1, 0 },
144 { 1, 1, 1, 0 },
145 { 0, 0, 0, 1 },
146 { 0, 1, 0, 1 },
147 { 1, 0, 0, 1 },
148 { 1, 1, 0, 1 },
149 { 0, 0, 1, 1 },
150 { 0, 1, 1, 1 },
151 { 1, 0, 1, 1 },
152 { 1, 1, 1, 1 },
153 { 0, 2, 0, 2 },
154 { 1, 2, 0, 2 },
155 { 0, 2, 1, 2 },
156 { 1, 2, 1, 2 },
157 { 3, 3, 0, 0 },
158 { 3, 3, 1, 0 },
159 { 3, 3, 0, 1 },
160 { 3, 3, 1, 1 },
161 { 3, 4, 0, 2 },
162 { 3, 4, 1, 2 },
163 { 2, 0, 2, 0 },
164 { 2, 1, 2, 0 },
165 { 2, 0, 2, 1 },
166 { 2, 1, 2, 1 },
167 { 2, 2, 2, 2 },
168 { 4, 3, 2, 0 },
169 { 4, 3, 2, 1 },
170 { 4, 4, 2, 2 },
171 { 0, 0, 3, 3 },
172 { 0, 1, 3, 3 },
173 { 1, 0, 3, 3 },
174 { 1, 1, 3, 3 },
175 { 0, 2, 3, 4 },
176 { 1, 2, 3, 4 },
177 { 3, 3, 3, 3 },
178 { 3, 4, 3, 4 },
179 { 2, 0, 4, 3 },
180 { 2, 1, 4, 3 },
181 { 2, 2, 4, 4 },
182 { 4, 3, 4, 3 },
183 { 4, 4, 4, 4 },
184 { 5, 5, 5, 5 },
185
186 { 5, 5, 5, 5 },
187 { 6, 6, 6, 6 },
188 { 7, 7, 7, 7 },
189 { 7, 6, 7, 6 },
190 { 8, 8, 8, 8 },
191 { 16, 6, 8, 15 },
192 { 7, 7, 8, 8 },
193 { 7, 6, 8, 15 },
194 { 9, 9, 9, 9 },
195 { 6, 6, 9, 9 },
196 { 7, 17, 14, 9 },
197 { 7, 6, 14, 9 },
198 { 8, 9, 8, 9 },
199 { 16, 6, 8, 9 },
200 { 7, 17, 8, 9 },
201 { 7, 6, 8, 9 },
202 { 10, 10, 10, 10 },
203 { 7, 10, 14, 10 },
204 { 16, 10, 8, 10 },
205 { 7, 10, 8, 10 },
206 { 11, 11, 11, 11 },
207 { 11, 11, 8, 15 },
208 { 11, 11, 14, 9 },
209 { 11, 11, 8, 9 },
210 { 14, 14, 14, 14 },
211 { 14, 14, 8, 14 },
212 { 12, 12, 12, 12 },
213 { 12, 6, 12, 15 },
214 { 12, 17, 12, 9 },
215 { 12, 6, 12, 9 },
216 { 12, 10, 12, 10 },
217 { 15, 15, 15, 15 },
218 { 15, 15, 15, 9 },
219 { 15, 14, 12, 10 },
220 { 13, 13, 13, 13 },
221 { 16, 6, 13, 13 },
222 { 7, 17, 13, 13 },
223 { 7, 6, 13, 13 },
224 { 16, 16, 16, 16 },
225 { 7, 16, 16, 16 },
226 { 11, 11, 13, 13 },
227 { 11, 14, 13, 16 },
228 { 17, 17, 17, 17 },
229 { 17, 6, 17, 17 },
230 { 12, 10, 17, 16 },
231 { 15, 11, 17, 13 },
232 { 15, 14, 17, 16 },
233 { 18, 18, 18, 18 }
234 };
235
236 struct tile_move_data
237 {
238 int32_t copies;
239 int32_t dest_first;
240 int32_t dest_last;
241 int32_t src_first;
242 int32_t src_last;
243 int32_t dest_top;
244 int32_t dest_bottom;
245 int32_t src_top;
246 int32_t src_bottom;
247 int32_t src_left, src_right;
248 int32_t src_width, src_height;
249 int32_t dest_left, dest_right;
250 int32_t dest_width, dest_height;
251 int32_t rows, cols;
252 bool rect, move;
253
254 tile_move_data()
255 {
256 copies = dest_first = dest_last = src_first = src_last = dest_top =
257 dest_bottom = src_top = src_bottom = src_left = src_right =
258 src_width = src_height = dest_left = dest_right = dest_width =
259 dest_height = rows = cols = 0;
260 rect = move = false;
261 }
262
263 tile_move_data(tile_move_data const& other)
264 {
265 copy(other);
266 }
267
268 tile_move_data& operator=(tile_move_data const& other)
269 {
270 copy(other);
271 return *this;
272 }
273
274 void copy(tile_move_data const& other)
275 {
276 copies = other.copies;
277 dest_first = other.dest_first;
278 dest_last = other.dest_last;
279 src_first = other.src_first;
280 src_last = other.src_last;
281 dest_top = other.dest_top;
282 dest_bottom = other.dest_bottom;
283 src_top = other.src_top;
284 src_bottom = other.src_bottom;
285 src_left = other.src_left;
286 src_right = other.src_right;
287 src_width = other.src_width;
288 src_height = other.src_height;
289 dest_left = other.dest_left;
290 dest_right = other.dest_right;
291 dest_width = other.dest_width;
292 dest_height = other.dest_height;
293 rows = other.rows;
294 cols = other.cols;
295 rect = other.rect;
296 move = other.move;
297 }
298
299 void flip()
300 {
301 zc_swap(src_first, dest_first);
302 zc_swap(src_last, dest_last);
303 zc_swap(src_top, dest_top);
304 zc_swap(src_bottom, dest_bottom);
305 zc_swap(src_left, dest_left);
306 zc_swap(src_right, dest_right);
307 zc_swap(src_width, dest_width);
308 zc_swap(src_height, dest_height);
309 }
310 };
311 bool do_movetile_united(tile_move_data const& tmd);
312
313 struct combo_move_data
314 {
315 int32_t tile, tile2, copy1, copycnt;
316 combo_move_data() : tile(0), tile2(0), copy1(0), copycnt(0){}
317 combo_move_data(combo_move_data const& other)
318 {
319 copy(other);
320 }
321 combo_move_data& operator=(combo_move_data const& other)
322 {
323 copy(other);
324 return *this;
325 }
326 void copy(combo_move_data const& other)
327 {
328 tile = other.tile;
329 tile2 = other.tile2;
330 copy1 = other.copy1;
331 copycnt = other.copycnt;
332 }
333
334 void flip()
335 {
336 int32_t tcnt = tile2-tile+1;
337 int32_t cpy2 = copy1+copycnt-1;
338 zc_swap(tile,copy1);
339 tile2 = cpy2;
340 copycnt = tcnt;
341 }
342 };
343
344 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing = false);
345 static optional<ComboMoveUndo> last_combo_move_list;
346 static optional<TileMoveUndo> last_tile_move_list;
347
348 int refl_flags = 0;
349 enum
350 {
351 REFL_90CW, REFL_HFLIP,
352 REFL_90CCW, REFL_VFLIP,
353 REFL_180, REFL_DBLFLIP,
354 REFL_MAX
355 };
356 const char *reflbtn_names[] =
357 {
358 "90 CW", "HFlip",
359 "90 CCW", "VFlip",
360 "180 Rot", "Diag Flip"
361 };
362 int bgmode = 0, xmode = 0;
363 const char *bgmodebtn_names[] =
364 {
365 "BG Color 0", "BG Trans."
366 };
367 const char *xmodebtn_names[] =
368 {
369 "X", "No X"
370 };
371 enum
372 {
373 XMODE_X, XMODE_NOX,
374 XMODE_MAX
375 };
376 enum
377 {
378 BGMODE_0, BGMODE_TRANSP,
379 BGMODE_MAX
380 };
381
382 void merge_tiles(int32_t dest_tile, int32_t src_quarter1, int32_t src_quarter2, int32_t src_quarter3, int32_t src_quarter4)
383 {
384 int32_t size=tilesize(newtilebuf[dest_tile].format)>>4;
385 int32_t size2=size>>1;
386
387 if(newtilebuf[dest_tile].data==NULL)
388 {
389 reset_tile(newtilebuf, dest_tile, newtilebuf[src_quarter1>>2].format);
390 }
391
392 int32_t i=0;
393
394 if((dest_tile<<2)+i!=src_quarter1)
395 {
396 for(int32_t j=0; j<8; ++j)
397 {
398 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter1>>2].data[((j+((src_quarter1&2)<<2))*size)+((src_quarter1&1)*size2)]), size2);
399 }
400 }
401
402 i=1;
403
404 if((dest_tile<<2)+i!=src_quarter2)
405 {
406 for(int32_t j=0; j<8; ++j)
407 {
408 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter2>>2].data[((j+((src_quarter2&2)<<2))*size)+((src_quarter2&1)*size2)]), size2);
409 }
410 }
411
412 i=2;
413
414 if((dest_tile<<2)+i!=src_quarter3)
415 {
416 for(int32_t j=0; j<8; ++j)
417 {
418 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter3>>2].data[((j+((src_quarter3&2)<<2))*size)+((src_quarter3&1)*size2)]), size2);
419 }
420 }
421
422 i=3;
423
424 if((dest_tile<<2)+i!=src_quarter4)
425 {
426 for(int32_t j=0; j<8; ++j)
427 {
428 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter4>>2].data[((j+((src_quarter4&2)<<2))*size)+((src_quarter4&1)*size2)]), size2);
429 }
430 }
431 }
432
433 static void make_combos(int32_t startTile, int32_t endTile, int32_t cs)
434 {
435 al_trace("inside make_combos()\n");
436 int32_t startCombo=0;
437
438 if(!select_combo_2(startCombo,cs))
439 return;
440
441 int32_t temp=combobuf[startCombo].o_tile;
442 combobuf[startCombo].set_tile(startTile);
443
444 if(!edit_combo(startCombo, false, cs))
445 {
446 combobuf[startCombo].set_tile(temp);
447 return;
448 }
449
450 go_combos();
451
452 for(int32_t i=0; i<=endTile-startTile; i++)
453 {
454 combobuf[startCombo+i]=combobuf[startCombo];
455 combobuf[startCombo+i].set_tile(startTile+i);
456 }
457
458 setup_combo_animations();
459 setup_combo_animations2();
460 }
461
462 static void make_combos_rect(int32_t top, int32_t left, int32_t numRows, int32_t numCols, int32_t cs)
463 {
464 int32_t startCombo=0;
465
466 if(!select_combo_2(startCombo, cs))
467 return;
468
469 int32_t startTile=top*TILES_PER_ROW+left;
470 int32_t temp=combobuf[startCombo].o_tile;
471 combobuf[startCombo].set_tile(startTile);
472
473 if(!edit_combo(startCombo, false, cs))
474 {
475 al_trace("make_combos_rect() early return\n");
476 combobuf[startCombo].set_tile(temp);
477 return;
478 }
479
480 bool smartWrap=false;
481 if(numCols!=4 && numRows>1)
482 {
483 char buf[64];
484 if(numCols<4)
485 sprintf(buf, "Limit to %d column%s?", numCols, numCols==1 ? "" : "s");
486 else
487 sprintf(buf, "Fit to 4 columns?"); // Meh, whatever.
488 int32_t ret=jwin_alert("Wrapping", buf, NULL, NULL, "&Yes", "&No", 'y', 'n', get_zc_font(font_lfont));
489 if(ret==1)
490 smartWrap=true;
491 }
492
493 go_combos();
494
495 int32_t combo=startCombo-1;
496 for(int32_t row=0; row<numRows; row++)
497 {
498 for(int32_t col=0; col<numCols; col++)
499 {
500 int32_t tile=startTile+row*TILES_PER_ROW+col;
501 if(smartWrap)
502 // Add 4 per row, and another numRows*4 for every 4 columns
503 // (col&0xFC==col/4*4), and then the column %4
504 combo=startCombo+4*row+(col&0xFC)*numRows+col%4;
505 else
506 combo++;
507
508 combobuf[combo]=combobuf[startCombo];
509 combobuf[combo].set_tile(tile);
510 }
511 }
512
513 setup_combo_animations();
514 setup_combo_animations2();
515 }
516
517 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t c);
518
519 static bool nogotiles = false;
520 static bool nogocombos = false;
521
522 void go_tiles()
523 {
524 if(nogotiles) return;
525 last_tile_move_list = nullopt;
526 for(int32_t i=0; i<NEWMAXTILES; ++i)
527 {
528 newundotilebuf[i].format=newtilebuf[i].format;
529
530 if(newundotilebuf[i].data!=NULL)
531 {
532 free(newundotilebuf[i].data);
533 }
534
535 newundotilebuf[i].data=(byte *)malloc(tilesize(newundotilebuf[i].format));
536
537 if(newundotilebuf[i].data==NULL)
538 {
539 Z_error_fatal("Unable to initialize undo tile #%ld.\n", i);
540 }
541
542 memcpy(newundotilebuf[i].data,newtilebuf[i].data,tilesize(newundotilebuf[i].format));
543 }
544 }
545
546 void go_slide_tiles(int32_t columns, int32_t rows, int32_t top, int32_t left)
547 {
548 for(int32_t c=0; c<columns; c++)
549 {
550 for(int32_t r=0; r<rows; r++)
551 {
552 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
553 newundotilebuf[t].format=newtilebuf[t].format;
554
555 if(newundotilebuf[t].data!=NULL)
556 {
557 free(newundotilebuf[t].data);
558 }
559
560 newundotilebuf[t].data=(byte *)malloc(tilesize(newundotilebuf[t].format));
561
562 if(newundotilebuf[t].data==NULL)
563 {
564 Z_error_fatal("Unable to initialize undo tile #%ld.\n", t);
565 }
566
567 memcpy(newundotilebuf[t].data,newtilebuf[t].data,tilesize(newundotilebuf[t].format));
568 }
569 }
570 }
571
572 void comeback_tiles()
573 {
574 if(last_tile_move_list)
575 {
576 last_tile_move_list->undo();
577 last_tile_move_list = nullopt;
578 }
579 for(dword i=0; i<NEWMAXTILES; ++i)
580 {
581 if(newtilebuf[i].format != newundotilebuf[i].format || !newtilebuf[i].data)
582 {
583 newtilebuf[i].format = newundotilebuf[i].format;
584
585 if(newtilebuf[i].data!=NULL)
586 free(newtilebuf[i].data);
587 newtilebuf[i].data=(byte *)malloc(tilesize(newtilebuf[i].format));
588 if(newtilebuf[i].data==NULL)
589 Z_error_fatal("Unable to initialize tile #%ld.\n", i);
590 }
591
592 memcpy(newtilebuf[i].data,newundotilebuf[i].data,tilesize(newtilebuf[i].format));
593 }
594
595 register_blank_tiles();
596 register_used_tiles();
597 }
598
599 void go_combos()
600 {
601 if(nogocombos) return;
602 last_combo_move_list = nullopt;
603
604 undocombobuf = combobuf;
605 }
606
607 void comeback_combos()
608 {
609 if(last_combo_move_list)
610 {
611 last_combo_move_list->undo();
612 last_combo_move_list = nullopt;
613 }
614
615 combobuf = undocombobuf;
616 }
617
618 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t s)
619 {
620 line(dest,x,y,x+s,y+s,c);
621 line(dest,x+s,y,x,y+s,c);
622 }
623 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t w, int32_t h)
624 {
625 line(dest,x,y,x+w,y+h,c);
626 line(dest,x+w,y,x,y+h,c);
627 }
628
629 enum {gm_light, gm_dark, gm_max};
630 int32_t gridmode=gm_light;
631
632 bool has_selection()
633 {
634 for(int32_t i=1; i<17; ++i)
635 {
636 for(int32_t j=1; j<17; ++j)
637 {
638 if(selection_grid[i][j])
639 {
640 return true;
641 }
642 }
643 }
644
645 return false;
646 }
647
648 void draw_selection_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
649 {
650 drawing_mode(DRAW_MODE_COPY_PATTERN, selection_pattern, selection_anchor>>3, 0);
651
652 for(int32_t i=1; i<18; ++i)
653 {
654 for(int32_t j=1; j<18; ++j)
655 {
656 // zoomtile16(screen2,tile,79,31,cs,flip,8);
657 if(selection_grid[i-1][j]!=selection_grid[i][j])
658 {
659 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
660 }
661
662 if(selection_grid[i][j-1]!=selection_grid[i][j])
663 {
664 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
665 }
666 }
667 }
668
669 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
670 // selection_anchor=(selection_anchor+1)%64;
671 }
672
673 bool is_selecting()
674 {
675 return (selecting_x1>-1&&selecting_x2>-1&&selecting_y1>-1&&selecting_y2>-1);
676 }
677
678 void draw_selecting_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
679 {
680 int32_t x1=zc_min(selecting_x1,selecting_x2);
681 int32_t x2=zc_max(selecting_x1,selecting_x2);
682 int32_t y1=zc_min(selecting_y1,selecting_y2);
683 int32_t y2=zc_max(selecting_y1,selecting_y2);
684
685 // rect(dest, x+(x1*scale2), y+(y1*scale2), x+((x2+1)*scale2), y+((y2+1)*scale2), 255);
686 for(int32_t i=1; i<18; ++i)
687 {
688 for(int32_t j=1; j<18; ++j)
689 {
690 drawing_mode(DRAW_MODE_COPY_PATTERN, selecting_pattern, selection_anchor>>3, 0);
691
692 if(((j>=y1+1)&&(j<=y2+1))&&((i==x1+1)||(i==x2+2)))
693 {
694 if(selection_grid[i-1][j]!=selection_grid[i][j])
695 {
696 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
697 }
698
699 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
700 }
701
702 if(((i>=x1+1)&&(i<=x2+1))&&((j==y1+1)||(j==y2+2)))
703 {
704 if(selection_grid[i][j-1]!=selection_grid[i][j])
705 {
706 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
707 }
708
709 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
710 }
711 }
712 }
713
714 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
715 // selection_anchor=(selection_anchor+1)%64;
716 }
717
718 void unfloat_selection();
719 bool floating_sel = false;
720 byte floatsel[256];
721 byte undofloatsel[256];
722 bool undo_is_floatsel = false;
723
724
725 void add_color_to_selection(int32_t color)
726 {
727 unfloat_selection();
728 for(int32_t i=1; i<17; ++i)
729 {
730 for(int32_t j=1; j<17; ++j)
731 {
732 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
733 {
734 selection_grid[i][j]=1;
735 }
736 }
737 }
738 }
739
740 void remove_color_from_selection(int32_t color)
741 {
742 unfloat_selection();
743 for(int32_t i=1; i<17; ++i)
744 {
745 for(int32_t j=1; j<17; ++j)
746 {
747 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
748 {
749 selection_grid[i][j]=0;
750 }
751 }
752 }
753 }
754
755 void intersect_color_with_selection(int32_t color)
756 {
757 unfloat_selection();
758 for(int32_t i=1; i<17; ++i)
759 {
760 for(int32_t j=1; j<17; ++j)
761 {
762 if((unpackbuf[((j-1)<<4)+(i-1)]==color)&&(selection_grid[i][j]==1))
763 {
764 selection_grid[i][j]=1;
765 }
766 else
767 {
768 selection_grid[i][j]=0;
769 }
770 }
771 }
772 }
773
774 bool is_in_selection(int32_t x, int32_t y)
775 {
776 x %= 16; y %= 16;
777 if(x < 0) x = (16 - abs(x));
778 if(y < 0) y = (16 - abs(y));
779 return (!has_selection()||(selection_grid[x+1][y+1]!=0));
780 }
781
782 void zoomtile16(BITMAP *dest,int32_t tile,int32_t x,int32_t y,int32_t cset,int32_t flip,int32_t m)
783 {
784 // rectfill(dest,x,y,x+(16*m),y+(16*m),gridmode==gm_light?jwin_pal[jcMEDLT]:jwin_pal[jcDARK]);
785 int gridcol = gridmode==gm_light?vc(7):vc(8);
786
787 cset <<= 4;
788 if(newtilebuf[tile].format>tf4Bit)
789 cset=0;
790
791 int g = hide_grid ? 1 : 0;
792 byte transp_col = (bgmode == BGMODE_TRANSP ? jwin_pal[jcBOX] : 0+cset);
793 rectfill(dest,x,y,x+(16*m)+g,y+(16*m)+g,transp_col);
794
795 unpack_tile(newtilebuf, tile, 0, false);
796 byte *si = unpackbuf;
797 for(int32_t cy=0; cy<16; cy++)
798 {
799 for(int32_t cx=0; cx<16; cx++)
800 {
801 byte col = (floating_sel && floatsel[cx+(cy<<4)]) ? floatsel[cx+(cy<<4)] : *si;
802 int32_t dx = ((flip&1)?15-cx:cx)*m;
803 int32_t dy = ((flip&2)?15-cy:cy)*m;
804 if(col)
805 rectfill(dest,x+dx,y+dy,x+dx+m-1,y+dy+m-1,col+cset);
806
807 if(!col && xmode == XMODE_X)
808 little_x(dest,x+dx+m/4,y+dy+m/4,invcol,m/2);
809
810 ++si;
811 }
812 }
813
814 if(!hide_grid)
815 {
816 for(int cx = 0; cx <= 16; ++cx)
817 vline(dest,x+(cx*m),y,y+(16*m)-1,gridcol);
818 for(int cy = 0; cy <= 16; ++cy)
819 hline(dest,x,y+(cy*m),x+(16*m)-1,gridcol);
820 }
821
822 if(show_quartgrid)
823 {
824 int offs = (8*m);
825 const int RAD = 3;
826 rectfill(dest,x+offs-RAD,y,x+offs+RAD,y+(16*m),gridcol);
827 rectfill(dest,x,y+offs-RAD,x+(16*m),y+offs+RAD,gridcol);
828 }
829
830 if(has_selection()||is_selecting())
831 {
832 selection_anchor=(selection_anchor+1)%64;
833
834 if(has_selection()||is_selecting())
835 draw_selection_outline(dest, x, y, m);
836
837 if(is_selecting())
838 draw_selecting_outline(dest, x, y, m);
839 }
840 }
841
842 void draw_text_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,int32_t flags,bool jwin)
843 {
844 if(!jwin)
845 {
846 if(flags&D_SELECTED)
847 {
848 zc_swap(fg,bg);
849 }
850
851 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
852 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
853 rect(dest,x,y,x+w-2,y+h-2,fg);
854 textout_centre_ex(dest,font,text,(x+x+w)>>1,((y+y+h)>>1)-4,fg,-1);
855 }
856 else
857 {
858 jwin_draw_text_button(dest, x, y, w, h, text, flags, true);
859 }
860 }
861
862 void draw_icon_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,int icon,int32_t bg,int32_t fg,int32_t flags,bool jwin)
863 {
864 if(!jwin)
865 {
866 if(flags&D_SELECTED)
867 {
868 zc_swap(fg,bg);
869 }
870
871 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
872 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
873 rect(dest,x,y,x+w-2,y+h-2,fg);
874 jwin_draw_icon(dest,x+w/2,y+h/2,fg,icon,icon_proportion(icon,w,h),true);
875 }
876 else
877 {
878 jwin_draw_icon_button(dest, x, y, w, h, icon, flags, true);
879 }
880 }
881
882 void draw_layer_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t flags)
883 {
884 if(flags&D_SELECTED)
885 {
886 rect(dest, x, y, x+w-1, y+h-1, jwin_pal[jcDARK]);
887 ++x;
888 ++y;
889 --w;
890 --h;
891 }
892 rectfill(dest,x+1,y+1,x+w-3,y+h-3,jwin_pal[(flags&D_SELECTED ? jcMEDDARK : jcBOX)]);
893 jwin_draw_frame(dest, x, y, w, h, (flags&D_SELECTED ? FR_DARK : FR_BOX));
894
895 //Forcibly fit the text within the button
896 char buf[512] = {0};
897 strcpy(buf, text);
898
899 bool dis = (flags&D_DISABLED);
900 auto hei = text_height(font);
901 auto len = text_length(font,buf);
902 auto borderwid = 8;
903 if(len > w - borderwid + (dis ? 1 : 0))
904 {
905 auto ind = strlen(buf) - 1;
906 auto dotcount = 0;
907 while(len > w - borderwid + (dis ? 1 : 0))
908 {
909 if(dotcount >= 2)
910 buf[ind+2] = 0;
911 else ++dotcount;
912 buf[ind--] = '.';
913 len = text_length(font,buf);
914 }
915 }
916 if(dis)
917 {
918 ++len; ++hei;
919 }
920 BITMAP* tmp = create_bitmap_ex(8,len,hei);
921 clear_bitmap(tmp);
922 if(dis)
923 {
924 textout_ex(tmp,font,buf,1,1,jwin_pal[jcLIGHT],-1);
925 textout_ex(tmp,font,buf,0,0,jwin_pal[jcDISABLED_FG],-1);
926 }
927 else
928 textout_ex(tmp,font,buf,0,0,jwin_pal[jcBOXFG],-1);
929 auto tx = x+((w-len)/2);
930 auto ty = y+((h-hei)/2);
931 if(len > w-borderwid)
932 {
933 tx = x+borderwid/2;
934 len = w-borderwid;
935 }
936 if(hei > h-borderwid)
937 {
938 ty = y+borderwid/2;
939 hei = h-borderwid;
940 }
941 masked_blit(tmp,dest, 0,0, tx,ty, len, hei);
942 destroy_bitmap(tmp);
943 }
944
945 bool do_layer_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text, int32_t flags, bool toggleflag)
946 {
947 bool over=false;
948
949 while(gui_mouse_b())
950 {
951 //vsync();
952 if(mouse_in_rect(x,y,w,h))
953 {
954 if(!over)
955 {
956 vsync();
957 draw_layer_button(screen, x, y, w, h, text, flags^D_SELECTED);
958 over=true;
959
960 update_hw_screen();
961 }
962 }
963 else
964 {
965 if(over)
966 {
967 vsync();
968 draw_layer_button(screen, x, y, w, h, text, flags);
969 over=false;
970
971 update_hw_screen();
972 }
973 }
974 rest(1);
975 }
976
977 if(over)
978 {
979 vsync();
980 draw_layer_button(screen, x, y, w, h, text, toggleflag ? flags^D_SELECTED : flags);
981
982 update_hw_screen();
983 }
984
985 return over;
986 }
987
988 bool do_text_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,bool jwin, bool sel)
989 {
990 bool over=false;
991
992 while(gui_mouse_b())
993 {
994 custom_vsync();
995
996 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
997 {
998 if(!over)
999 {
1000 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1001 over=true;
1002 }
1003 }
1004 else
1005 {
1006 if(over)
1007 {
1008 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?D_SELECTED:0,jwin);
1009 over=false;
1010 }
1011 }
1012 }
1013
1014 if(over)
1015 {
1016 custom_vsync();
1017 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1018 }
1019
1020 return over;
1021 }
1022
1023 void draw_graphics_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,int32_t flags,bool jwin,bool overlay)
1024 {
1025 if(!jwin)
1026 {
1027 if(flags&D_SELECTED)
1028 {
1029 zc_swap(fg,bg);
1030 }
1031
1032 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
1033 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
1034 rect(dest,x,y,x+w-2,y+h-2,fg);
1035 int32_t g = (flags & D_SELECTED) ? 1 : 0;
1036
1037 if(overlay)
1038 {
1039 masked_blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1040 }
1041 else
1042 {
1043 blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1044 }
1045 }
1046 else
1047 {
1048 jwin_draw_graphics_button(dest, x, y, w, h, bmp, bmp2, flags, false, overlay);
1049 }
1050 }
1051
1052 bool do_graphics_button(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1053 {
1054 bool over=false;
1055
1056 while(gui_mouse_b())
1057 {
1058 custom_vsync();
1059
1060 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1061 {
1062 if(!over)
1063 {
1064 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1065 over=true;
1066 }
1067 }
1068 else
1069 {
1070 if(over)
1071 {
1072 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1073 over=false;
1074 }
1075 }
1076 }
1077
1078 return over;
1079 }
1080
1081 bool do_graphics_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1082 {
1083 bool over=false;
1084
1085 while(gui_mouse_b())
1086 {
1087 custom_vsync();
1088
1089 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1090 {
1091 if(!over)
1092 {
1093 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1094 over=true;
1095 }
1096 }
1097 else
1098 {
1099 if(over)
1100 {
1101 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1102 over=false;
1103 }
1104 }
1105 }
1106
1107 if(over)
1108 {
1109 custom_vsync();
1110 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1111 }
1112
1113 return over;
1114 }
1115 // circle(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1116 // circlefill(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1117
1118 void draw_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg, int32_t value)
1119 {
1120 //these are here to bypass compiler warnings about unused arguments
1121 bg=bg;
1122 fg=fg;
1123
1124 int32_t r, center;
1125
1126 for(int32_t k=0; k<7; k++)
1127 {
1128 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1129 {
1130 // circle(dest, x+(k*25)+4, y+4, 4, fg);
1131 // circlefill(dest, x+(k*25)+4, y+4, 2, (value==k)?fg:bg);
1132 //*
1133 r = 9/2;
1134
1135 center = x+(k*25)+r;
1136 rectfill(dest, x+(k*25), y, x+(k*25)+9-1, y+9-1, jwin_pal[jcBOX]);
1137
1138 circlefill(dest, center, y+r, r, jwin_pal[jcLIGHT]);
1139 arc(dest, center, y+r, itofix(32), itofix(160), r, jwin_pal[jcMEDDARK]);
1140 circlefill(dest, center, y+r, r-1, jwin_pal[jcMEDLT]);
1141 arc(dest, center, y+r, itofix(32), itofix(160), r-1, jwin_pal[jcDARK]);
1142 circlefill(dest, center, y+r, r-2, jwin_pal[jcLIGHT]);
1143
1144 if(value==k)
1145 {
1146 circlefill(dest, center, y+r, r-3, jwin_pal[jcDARK]);
1147 }
1148
1149 //*/
1150 }
1151 }
1152 }
1153
1154 void do_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg,int32_t &value)
1155 {
1156 while(gui_mouse_b())
1157 {
1158 custom_vsync();
1159
1160 for(int32_t k=0; k<7; k++)
1161 {
1162 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1163 {
1164 //if on radio button
1165 if(isinRect(gui_mouse_x(),gui_mouse_y(),x+(k*25),y,x+(k*25)+8,y+8))
1166 {
1167 value=k;
1168 draw_layerradio(dest,x,y,bg,fg,value);
1169 refresh(rMENU);
1170 }
1171 }
1172 }
1173 }
1174 }
1175
1176 //*************** tile flood fill stuff **************
1177
1178 byte tf_c;
1179 byte tf_u;
1180
1181 void tile_floodfill_rec(int32_t x,int32_t y)
1182 {
1183 if(is_in_selection(x,y))
1184 {
1185 while(x>0 && (unpackbuf[(y<<4)+x-1] == tf_u))
1186 --x;
1187
1188 while(x<=15 && (unpackbuf[(y<<4)+x] == tf_u))
1189 {
1190 if(is_in_selection(x,y))
1191 {
1192 unpackbuf[(y<<4)+x] = tf_c;
1193 }
1194
1195 if(y>0 && (unpackbuf[((y-1)<<4)+x] == tf_u))
1196 tile_floodfill_rec(x,y-1);
1197
1198 if(y<15 && (unpackbuf[((y+1)<<4)+x] == tf_u))
1199 tile_floodfill_rec(x,y+1);
1200
1201 ++x;
1202 }
1203 }
1204 }
1205
1206 void tile_floodfill(int32_t tile,int32_t x,int32_t y,byte c)
1207 {
1208 if(is_in_selection(x,y))
1209 {
1210 if(floating_sel)
1211 {
1212 memcpy(unpackbuf, floatsel, 256);
1213 }
1214 else unpack_tile(newtilebuf, tile, 0, false);
1215 tf_c = c;
1216 tf_u = unpackbuf[(y<<4)+x];
1217
1218 if(tf_u != tf_c)
1219 tile_floodfill_rec(x,y);
1220 if(floating_sel)
1221 {
1222 memcpy(floatsel, unpackbuf, 256);
1223 }
1224 else pack_tile(newtilebuf,unpackbuf,tile);
1225 }
1226 }
1227
1228 //***************** tile editor stuff *****************
1229 12 size_and_pos ok_button(302,562,71,21);
1230 12 size_and_pos cancel_button(376,562,71,21);
1231 12 size_and_pos edit_button(550,562,86,21);
1232 12 size_and_pos hlcbox(742,392,16,16);
1233 12 size_and_pos hov_prev(742,338,50,50);
1234 12 size_and_pos cpalette_4(648,416,4,4,64,64);
1235 12 size_and_pos cpalette_8(648,416,16,14,16,18);
1236 12 size_and_pos fg_prev(648,316,50,50);
1237 12 size_and_pos bg_prev(648+30,316+30,50,50);
1238 12 size_and_pos zoomtile(124,32,16,16,32,32);
1239 12 size_and_pos prev_til_1(648,31,96,96);
1240 12 size_and_pos prev_til_2(752,31,96,96);
1241 12 size_and_pos prev_til_3(648,135,96,96);
1242 12 size_and_pos prev_til_4(752,135,96,96);
1243 12 size_and_pos ref_til(14,189,96,96);
1244 12 size_and_pos status_info(648,308-(4*8),1,4,1,8);
1245 12 size_and_pos hover_info(742,338-(3*8),1,3,1,8);
1246 12 size_and_pos color_info(4,294,1,1,116,8);
1247 12 size_and_pos color_info_btn(24,294,96,21);
1248 12 size_and_pos tool_btns(22,29,2,4,39,39);
1249 12 size_and_pos x_btn(890,5,15,13);
1250 12 size_and_pos info_btn(872,5,15,13);
1251 12 size_and_pos hidegrid_cbox(124,552,16,16);
1252 12 size_and_pos quartgrid_cbox(124,572,16,16);
1253 12 size_and_pos reflbtn_grid(124,610,2,3,71,21);
1254 12 size_and_pos xmodebtn_grid(300,610,1,2,90,21);
1255 12 size_and_pos bgmodebtn_grid(390,610,1,2,90,21);
1256
1257 int32_t c1=1;
1258 int32_t c2=0;
1259 int32_t floating_tile = -1;
1260 int32_t tool = t_pen;
1261 int32_t old_tool = -1;
1262 int32_t tool_cur = -1;
1263 int32_t select_mode = 0;
1264 int32_t drawing=0;
1265 int32_t reftile = 0;
1266
1267 bool qgrid_tool(int tool)
1268 {
1269 switch(tool)
1270 {
1271 case t_pen:
1272 case t_fill:
1273 case t_recolor:
1274 case t_wand:
1275 return true;
1276 }
1277 return false;
1278 }
1279
1280 void set_tool_sprite(int tool, int type)
1281 {
1282 int spr = ZQM_NORMAL;
1283 switch(tool)
1284 {
1285 case t_pen: spr = ZQM_SWORD; break;
1286 case t_fill: spr = ZQM_POTION; break;
1287 case t_recolor: spr = ZQM_WAND; break;
1288 case t_eyedropper: spr = ZQM_LENS; break;
1289 case t_move: spr = ZQM_GLOVE_OPEN+type; break;
1290 case t_select: spr = ZQM_HOOK_PLAIN+type; break;
1291 case t_wand: spr = ZQM_SEL_WAND_PLAIN+type; break;
1292 }
1293 MouseSprite::set(spr);
1294 }
1295 void update_tool_cursor()
1296 {
1297 int32_t temp_mouse_x=gui_mouse_x();
1298 int32_t temp_mouse_y=gui_mouse_y();
1299
1300 int32_t type=0;
1301
1302 if(has_selection())
1303 {
1304 switch(tool)
1305 {
1306 case t_select:
1307 case t_wand:
1308 type+=select_mode;
1309 break;
1310 }
1311 }
1312
1313 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
1314 {
1315 if(tool_cur==-1)
1316 set_tool_sprite(tool,type);
1317
1318 tool_cur=tool;
1319 }
1320 else if(tool_cur != -1)
1321 {
1322 MouseSprite::set(ZQM_NORMAL);
1323 tool_cur = -1;
1324 }
1325 }
1326
1327 void draw_edit_scr(int32_t tile,int32_t flip,int32_t cs,byte *oldtile,bool create_tbar)
1328 {
1329 PALETTE tpal;
1330 static BITMAP *tbar = create_bitmap_ex(8,zq_screen_w-6, 18);
1331 static BITMAP *preview_bmp = create_bitmap_ex(8, 64, 64);
1332 jwin_draw_win(screen2, 0, 0, zq_screen_w, zq_screen_h, FR_WIN);
1333
1334 if(!create_tbar)
1335 {
1336 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1337 }
1338 else
1339 {
1340 jwin_draw_titlebar(tbar, 0, 0, zq_screen_w-6, 18, "", true, true);
1341 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1342 }
1343
1344 textprintf_ex(screen2,get_zc_font(font_lfont),5,5,jwin_pal[jcTITLEFG],-1,"Tile Editor (%d)",tile);
1345
1346 clear_to_color(preview_bmp, 0);
1347
1348 zc_swap(oldtile,newtilebuf[tile].data); //Put oldtile in the tile buffer
1349 jwin_draw_win(screen2, prev_til_1.x-2,prev_til_1.y-2, prev_til_1.w+4, prev_til_1.h+4, FR_DEEP);
1350 puttile16(preview_bmp,tile,0,0,cs,flip);
1351 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_1.x, prev_til_1.y, prev_til_1.w, prev_til_1.h);
1352
1353 clear_to_color(preview_bmp, 0);
1354 jwin_draw_win(screen2, prev_til_2.x-2,prev_til_2.y-2, prev_til_2.w+4, prev_til_2.h+4, FR_DEEP);
1355 overtile16(preview_bmp,tile,0,0,cs,flip);
1356 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_2.x, prev_til_2.y, prev_til_2.w, prev_til_2.h);
1357 zc_swap(oldtile,newtilebuf[tile].data); //Swap the real tile back to the buffer
1358
1359 unpack_tile(newtilebuf, tile, 0, true);
1360 if(floating_sel)
1361 for(auto q = 0; q < 256; ++q)
1362 if(floatsel[q])
1363 unpackbuf[q] = floatsel[q];
1364 byte tmptile[256];
1365 byte *tmpptr = tmptile;
1366 zc_swap(tmpptr,newtilebuf[tile].data); //Put temp data in the tile buffer
1367 pack_tile(newtilebuf,unpackbuf,tile);
1368 clear_to_color(preview_bmp, 0);
1369
1370 jwin_draw_win(screen2, prev_til_3.x-2,prev_til_3.y-2, prev_til_3.w+4, prev_til_3.h+4, FR_DEEP);
1371 puttile16(preview_bmp,tile,0,0,cs,flip);
1372 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_3.x, prev_til_3.y, prev_til_3.w, prev_til_3.h);
1373
1374 clear_to_color(preview_bmp, 0);
1375 jwin_draw_win(screen2, prev_til_4.x-2,prev_til_4.y-2, prev_til_4.w+4, prev_til_4.h+4, FR_DEEP);
1376 overtile16(preview_bmp,tile,0,0,cs,flip);
1377 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_4.x, prev_til_4.y, prev_til_4.w, prev_til_4.h);
1378
1379 if(reftile > 0)
1380 {
1381 clear_to_color(preview_bmp, 0);
1382 jwin_draw_win(screen2, ref_til.x-2,ref_til.y-2, ref_til.w+4, ref_til.h+4, FR_DEEP);
1383 overtile16(preview_bmp,reftile,0,0,cs,flip);
1384 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, ref_til.x, ref_til.y, ref_til.w, ref_til.h);
1385 }
1386
1387 //Color info
1388 {
1389 color_info.h = 1;
1390 if(showcolortip)
1391 {
1392 auto fh = color_info.yscale = text_height(font);
1393 int ty = color_info.y;
1394 if(reftile <= 0)
1395 ty -= ref_til.h + 8;
1396 int y = ty;
1397 int rx = color_info.x+color_info.xscale;
1398 gui_textout_ln(screen2,font,(unsigned char*)"Colors:",
1399 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1400 auto str = get_tile_colornames(tile,cs);
1401 size_t pos = 0;
1402 char buf[512] = {0};
1403 char cbuf[16] = {0};
1404 while(pos < str.size())
1405 {
1406 y += fh;
1407 if(y+fh > zq_screen_h)
1408 break; //Out of space!
1409 auto endpos = str.find_first_of('\n',pos);
1410
1411 if(endpos == std::string::npos)
1412 {
1413 strcpy(buf,str.substr(pos).c_str());
1414 pos = str.size();
1415 }
1416 else
1417 {
1418 strcpy(buf,str.substr(pos,endpos-pos+1).c_str());
1419 pos = endpos+1;
1420 }
1421 //Ensure the name fits horizontally
1422 if(text_length(font,buf) > color_info.xscale)
1423 {
1424 size_t pos = 0;
1425 for(; buf[pos]; ++pos)
1426 {
1427 if(buf[pos] == ':')
1428 {
1429 strcpy(cbuf, buf+pos);
1430 buf[pos] = 0;
1431 break;
1432 }
1433 }
1434 size_t clen = text_length(font,cbuf);
1435 size_t dotlen = text_length(font,"..");
1436
1437 while(pos > 0 && (dotlen+clen+text_length(font,buf) > color_info.xscale))
1438 buf[--pos] = 0;
1439 while(buf[pos] == ' ')
1440 buf[pos] = 0;
1441 strcat(buf,"..");
1442 strcat(buf,cbuf);
1443 }
1444 gui_textout_ln(screen2,font,(unsigned char const*)buf,
1445 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1446 ++color_info.h;
1447 }
1448 jwin_draw_frame(screen2,color_info.x-2,ty-2,(color_info.w*color_info.xscale)+4,(color_info.h*color_info.yscale)+4,FR_DEEP);
1449 }
1450 else
1451 {
1452 int ty = color_info_btn.y;
1453 if(reftile <= 0)
1454 ty -= ref_til.h + 8;
1455 draw_text_button(screen2,color_info_btn.x,ty,color_info_btn.w,color_info_btn.h,
1456 "Show Colors",vc(1),vc(14),0,true);
1457 }
1458 }
1459
1460 zc_swap(tmpptr,newtilebuf[tile].data); //Swap the real tile back to the buffer
1461
1462 jwin_draw_win(screen2, zoomtile.x-3, zoomtile.y-3, (zoomtile.w*zoomtile.xscale)+5, (zoomtile.h*zoomtile.yscale)+5, FR_DEEP);
1463 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
1464
1465 if(floating_sel)
1466 textprintf_ex(screen2,font,status_info.x,status_info.y+0,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Floating selection");
1467 textprintf_ex(screen2,font,status_info.x,status_info.y+(1*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile: %d",tile);
1468 if(newtilebuf[tile].format==tf8Bit)
1469 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"8-bit");
1470 else
1471 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cset: %d",cs);
1472
1473 PALETTE temppal;
1474
1475 //palette and mouse
1476 switch(newtilebuf[tile].format)
1477 {
1478 case tf4Bit:
1479 jwin_draw_win(screen2, cpalette_4.x-2, cpalette_4.y-2, (cpalette_4.xscale*cpalette_4.w)+4, (cpalette_4.yscale*cpalette_4.h)+4, FR_DEEP);
1480 get_palette(temppal);
1481
1482 for(int32_t i=0; i<cpalette_4.w*cpalette_4.h; i++)
1483 {
1484 size_and_pos const& s = cpalette_4.subsquare(i);
1485 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,CSET(cs)+i);
1486 }
1487
1488 little_x(screen2,cpalette_4.x+1,cpalette_4.y+1,invcol,cpalette_4.xscale-5,cpalette_4.yscale-5);
1489 break;
1490
1491 case tf8Bit:
1492 jwin_draw_win(screen2, cpalette_8.x-2, cpalette_8.y-2, (cpalette_8.xscale*cpalette_8.w)+4, (cpalette_8.yscale*cpalette_8.h)+4, FR_DEEP);
1493
1494 for(int32_t i=0; i<cpalette_8.w*cpalette_8.h; ++i)
1495 {
1496 size_and_pos const& s = cpalette_8.subsquare(i);
1497 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,i);
1498 }
1499
1500 little_x(screen2,cpalette_8.x+1,cpalette_8.y+1,invcol,cpalette_8.xscale-5,cpalette_8.yscale-5);
1501 break;
1502 }
1503
1504 rect(screen2, bg_prev.x, bg_prev.y, bg_prev.x+bg_prev.w-1, bg_prev.y+bg_prev.h-1, jwin_pal[jcTEXTFG]);
1505 rectfill(screen2, bg_prev.x+1, bg_prev.y+1, bg_prev.x+bg_prev.w-2, bg_prev.y+bg_prev.h-2, jwin_pal[jcTEXTBG]);
1506 rectfill(screen2, bg_prev.x+3, bg_prev.y+3, bg_prev.x+bg_prev.w-4, bg_prev.y+bg_prev.h-4, c2+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1507
1508 if(c2==0)
1509 {
1510 little_x(screen2, bg_prev.x+1, bg_prev.y+1, invcol, bg_prev.w-2, bg_prev.h-2);
1511 }
1512
1513 rect(screen2, fg_prev.x, fg_prev.y, fg_prev.x+fg_prev.w-1, fg_prev.y+fg_prev.h-1, jwin_pal[jcTEXTFG]);
1514 rectfill(screen2, fg_prev.x+1, fg_prev.y+1, fg_prev.x+fg_prev.w-2, fg_prev.y+fg_prev.h-2, jwin_pal[jcTEXTBG]);
1515 rectfill(screen2, fg_prev.x+3, fg_prev.y+3, fg_prev.x+fg_prev.w-4, fg_prev.y+fg_prev.h-4, c1+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1516
1517 if(c1==0)
1518 {
1519 little_x(screen2, fg_prev.x+1, fg_prev.y+1, invcol, fg_prev.w-2, fg_prev.h-2);
1520 }
1521
1522 draw_text_button(screen2,ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK",vc(1),vc(14),0,true);
1523 draw_text_button(screen2,cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel",vc(1),vc(14),0,true);
1524 draw_text_button(screen2,edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal",vc(1),vc(14),0,true);
1525 draw_checkbox(screen2,hlcbox.x, hlcbox.y, hlcbox.w, hlcbox.h, tthighlight);
1526 gui_textout_ln(screen2,font,(unsigned char*)"Highlight Hover",hlcbox.x+hlcbox.w+2,hlcbox.y+hlcbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1527
1528 draw_checkbox(screen2,quartgrid_cbox.x, quartgrid_cbox.y, quartgrid_cbox.w, quartgrid_cbox.h, show_quartgrid);
1529 gui_textout_ln(screen2,font,(unsigned char*)"Quarter Grid",quartgrid_cbox.x+quartgrid_cbox.w+2,quartgrid_cbox.y+quartgrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1530
1531 draw_checkbox(screen2,hidegrid_cbox.x, hidegrid_cbox.y, hidegrid_cbox.w, hidegrid_cbox.h, hide_grid);
1532 gui_textout_ln(screen2,font,(unsigned char*)"Hide Grid",hidegrid_cbox.x+hidegrid_cbox.w+2,hidegrid_cbox.y+hidegrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1533
1534 bool qgrd = show_quartgrid && qgrid_tool(tool);
1535 gui_textout_ln(screen2,font,(unsigned char*)"Quarter-Grid Draw Modes", reflbtn_grid.x, reflbtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],qgrd?0:D_DISABLED);
1536 for(int q = 0; q < REFL_MAX; ++q)
1537 {
1538 auto& sqr = reflbtn_grid.subsquare(q);
1539 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[q],vc(1),vc(14),qgrd ? ((refl_flags&(1<<q)) ? D_SELECTED : 0) : D_DISABLED,true);
1540 }
1541 gui_textout_ln(screen2,font,(unsigned char*)"Transparent Mode", xmodebtn_grid.x, xmodebtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1542 for(int q = 0; q < XMODE_MAX; ++q)
1543 {
1544 auto& sqr = xmodebtn_grid.subsquare(q);
1545 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[q],vc(1),vc(14),(xmode == q) ? D_SELECTED : 0,true);
1546 }
1547 for(int q = 0; q < BGMODE_MAX; ++q)
1548 {
1549 auto& sqr = bgmodebtn_grid.subsquare(q);
1550 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[q],vc(1),vc(14),(bgmode == q) ? D_SELECTED : 0,true);
1551 }
1552
1553 //tool buttons
1554 for(int32_t toolbtn = 0; toolbtn < t_max; ++toolbtn)
1555 {
1556 auto bmp = toolbtn+MOUSE_BMP_SWORD;
1557 int col = toolbtn%tool_btns.w;
1558 int row = toolbtn/tool_btns.w;
1559
1560 jwin_draw_button(screen2,tool_btns.x+(col*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale,tool==toolbtn?2:0,0);
1561 masked_stretch_blit(mouse_bmp_1x[bmp][0],screen2,0,0,16,16,tool_btns.x+(col*tool_btns.xscale)+3+(tool==toolbtn?1:0),tool_btns.y+3+(row*tool_btns.yscale)+(tool==toolbtn?1:0),tool_btns.xscale-7,tool_btns.yscale-7);
1562 }
1563
1564 //coordinates
1565 {
1566 auto mx = gui_mouse_x();
1567 auto my = gui_mouse_y();
1568 int32_t ind = zoomtile.rectind(mx,my);
1569 int32_t temp_x=ind%zoomtile.w;
1570 int32_t temp_y=ind/zoomtile.w;
1571 int color = -1;
1572
1573 bool is8b = newtilebuf[tile].format > tf4Bit;
1574 if(ind > -1)
1575 {
1576 char xbuf[16];
1577 sprintf(xbuf, "x: %d", temp_x);
1578 textprintf_ex(screen2,font,status_info.x,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%s",xbuf);
1579 textprintf_ex(screen2,font,status_info.x+text_length(font,xbuf)+8,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"y: %d",temp_y);
1580 unpack_tile(newtilebuf, tile, 0, false);
1581 byte *si = unpackbuf;
1582 si+=ind;
1583 color = *si;
1584 }
1585 else if(fg_prev.rect(mx,my))
1586 color = c1;
1587 else if(bg_prev.rect(mx,my))
1588 color = c2;
1589 else color = (is8b ? cpalette_8 : cpalette_4).rectind(mx,my);
1590 if(color > -1)
1591 {
1592 get_palette(tpal);
1593 char separator = ' ';
1594 char buf[512] = {0};
1595
1596 int realcol = color+(is8b?0:CSET(cs));
1597 bool xcolor = (is8b ? realcol == 0 : (realcol%16)==0);
1598 auto& c = tpal[realcol];
1599
1600 if(tthighlight)
1601 {
1602 size_and_pos const& mainsqr = is8b ? cpalette_8 : cpalette_4;
1603 size_and_pos const& csqr = mainsqr.subsquare(color);
1604
1605 int hlcol = getHighlightColor(tpal[realcol]);
1606 int hlthick = 4;
1607 int extraborder = is8b ? 8 : 0;
1608 int borderthick = hlthick+extraborder;
1609
1610 if(is8b)
1611 {
1612 highlight_sqr(screen2, 0xED, csqr.x, mainsqr.y, csqr.w, mainsqr.h*mainsqr.yscale, hlthick); //column
1613 highlight_sqr(screen2, 0xED, mainsqr.x, csqr.y, mainsqr.w*mainsqr.xscale, csqr.h, hlthick); //row
1614 }
1615 highlight_sqr(screen2, 0xED, csqr.x-borderthick, csqr.y-borderthick, csqr.w+borderthick*2, csqr.h+borderthick*2, hlthick); //square hl
1616 rectfill(screen2, csqr.x-extraborder, csqr.y-extraborder, csqr.x+csqr.w-1+extraborder, csqr.y+csqr.h-1+extraborder, realcol); //square color
1617 if(xcolor)
1618 little_x(screen2, csqr.x-extraborder+4, csqr.y-extraborder+4, invcol, csqr.w+(extraborder*2)-8, csqr.h+(extraborder*2)-8); //transparent X
1619 highlight_sqr(screen2, hlcol, csqr.x-extraborder, csqr.y-extraborder, csqr.w+extraborder*2, csqr.h+extraborder*2, 1); //highlight border
1620 }
1621
1622 sprintf(buf, "%02d %02d %02d %c(0x%02X %d)",c.r,c.g,c.b,separator,realcol,color);
1623 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(2*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1624
1625 strcpy(buf, get_color_name(realcol, is8b).c_str());
1626 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(1*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1627
1628 sprintf(buf, "#%02X%02X%02X", tpal[realcol].r,tpal[realcol].g,tpal[realcol].b);
1629 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(0),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1630
1631 rect(screen2, hov_prev.x, hov_prev.y, hov_prev.x+hov_prev.w-1, hov_prev.y+hov_prev.h-1, jwin_pal[jcTEXTFG]);
1632 rectfill(screen2, hov_prev.x+1, hov_prev.y+1, hov_prev.x+hov_prev.w-2, hov_prev.y+hov_prev.h-2, jwin_pal[jcTEXTBG]);
1633 rectfill(screen2, hov_prev.x+3, hov_prev.y+3, hov_prev.x+hov_prev.w-4, hov_prev.y+hov_prev.h-4, realcol);
1634 if(xcolor)
1635 little_x(screen2, hov_prev.x+1, hov_prev.y+1, invcol, hov_prev.w-2, hov_prev.h-2);
1636 }
1637 }
1638
1639 custom_vsync();
1640 blit(screen2,screen,0,0,0,0,zq_screen_w,zq_screen_w);
1641 update_tool_cursor();
1642 SCRFIX();
1643 }
1644
1645 void normalize(int32_t tile,int32_t tile2, bool rect_sel, int32_t flip)
1646 {
1647 unfloat_selection();
1648 if(tile>tile2)
1649 {
1650 zc_swap(tile, tile2);
1651 }
1652
1653 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
1654 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
1655
1656 int32_t start=tile;
1657 int32_t end=tile2;
1658
1659 // Might have top-right and bottom-left corners selected...
1660 if(rect_sel && TILECOL(tile)>TILECOL(tile2))
1661 {
1662 start=tile-(TILECOL(tile)-TILECOL(tile2));
1663 end=tile2+(TILECOL(tile)-TILECOL(tile2));
1664 }
1665
1666 for(int32_t temptile=start; temptile<=end; temptile++)
1667 {
1668 if(!rect_sel || ((TILECOL(temptile)>=left) && (TILECOL(temptile)<=left+columns-1)))
1669 {
1670 unpack_tile(newtilebuf, temptile, 0, true);
1671
1672 if(flip&1)
1673 {
1674 for(int32_t y=0; y<16; y++)
1675 {
1676 for(int32_t x=0; x<8; x++)
1677 {
1678 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[(y<<4)+15-x]);
1679 }
1680 }
1681 }
1682
1683 if(flip&2)
1684 {
1685 for(int32_t y=0; y<8; y++)
1686 {
1687 for(int32_t x=0; x<16; x++)
1688 {
1689 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[((15-y)<<4)+x]);
1690 }
1691 }
1692 }
1693
1694 pack_tile(newtilebuf,unpackbuf,temptile);
1695 }
1696 }
1697 }
1698
1699 void rotate_tile(int32_t tile, bool backward)
1700 {
1701 unfloat_selection();
1702 unpack_tile(newtilebuf, tile, 0, true);
1703 byte tempunpackbuf[256];
1704 byte tempx, tempy;
1705
1706 for(tempx=0; tempx<16; tempx++)
1707 {
1708 for(tempy=0; tempy<16; tempy++)
1709 {
1710 if(!backward)
1711 {
1712 tempunpackbuf[(tempy<<4)+tempx]=unpackbuf[((15-tempx)<<4)+tempy];
1713 }
1714 else
1715 {
1716 tempunpackbuf[((15-tempx)<<4)+tempy]=unpackbuf[(tempy<<4)+tempx];
1717 }
1718 }
1719 }
1720
1721 pack_tile(newtilebuf,tempunpackbuf,tile);
1722 }
1723
1724 static int32_t undocount=128;
1725 byte undotile[256];
1726
1727 void wrap_tile(int32_t tile, int32_t vertical, int32_t horizontal, bool clear)
1728 {
1729 byte buf[256];
1730
1731 for(int32_t i=0; i<undocount; i++)
1732 {
1733 newtilebuf[tile].data[i]=undotile[i];
1734 }
1735
1736 if(!(horizontal||vertical))
1737 {
1738 return;
1739 }
1740
1741 unpack_tile(newtilebuf, tile, 0, true);
1742
1743 for(int32_t i=0; i<256; i++)
1744 {
1745 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1746 buf[shift_ind] = unpackbuf[i];
1747 }
1748
1749 if(clear)
1750 {
1751 for(int32_t r=0; r<abs(vertical); r++)
1752 {
1753 for(int32_t c=0; c<16; c++)
1754 {
1755 buf[(vertical>0?r:15-r)*16+c]=0;
1756 }
1757 }
1758
1759 for(int32_t r=0; r<16; r++)
1760 {
1761 for(int32_t c=0; c<abs(horizontal); c++)
1762 {
1763 buf[r*16+(horizontal>0?c:15-c)]=0;
1764 }
1765 }
1766 }
1767
1768 pack_tile(newtilebuf,buf,tile);
1769 }
1770
1771 void wrap_sel_tile(int32_t vertical, int32_t horizontal)
1772 {
1773 byte buf[256];
1774
1775 if(!(horizontal||vertical))
1776 {
1777 return;
1778 }
1779
1780 memset(buf,0,256);
1781
1782 for(int32_t i=0; i<256; i++)
1783 {
1784 if(is_in_selection(i%16,i/16))
1785 {
1786 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1787 buf[shift_ind] = floatsel[i];
1788 }
1789 }
1790
1791 memcpy(floatsel,buf,256);
1792 }
1793
1794 void float_selection(int32_t tile, bool clear)
1795 {
1796 if(floating_sel) return;
1797 floating_sel = true;
1798 floating_tile = tile;
1799
1800 unpack_tile(newtilebuf, tile, 0, true);
1801
1802 for(auto q = 0; q < 256; ++q)
1803 {
1804 if(is_in_selection(q%16,q/16))
1805 {
1806 floatsel[q] = unpackbuf[q];
1807 unpackbuf[q] = clear ? 0 : c2;
1808 }
1809 else floatsel[q] = 0;
1810 }
1811
1812 pack_tile(newtilebuf,unpackbuf,tile);
1813 }
1814
1815 void unfloat_selection()
1816 {
1817 if(!floating_sel) return;
1818 floating_sel = false;
1819
1820 unpack_tile(newtilebuf, floating_tile, 0, true);
1821
1822 for(auto q = 0; q < 256; ++q)
1823 {
1824 if(floatsel[q])
1825 {
1826 unpackbuf[q] = floatsel[q];
1827 }
1828 }
1829
1830 pack_tile(newtilebuf,unpackbuf,floating_tile);
1831 floating_tile = -1;
1832 }
1833
1834 void shift_tile_colors(int32_t tile, int32_t amount, bool ignore_transparent)
1835 {
1836 if(floating_sel)
1837 {
1838 for(auto q = 0; q < 256; ++q)
1839 {
1840 if(ignore_transparent && floatsel[q]==0)
1841 continue;
1842 floatsel[q]=wrap(floatsel[q]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1843 }
1844 return;
1845 }
1846
1847 byte buf[256];
1848 unpack_tile(newtilebuf, tile, 0, true);
1849
1850 for(int32_t i=0; i<256; i++)
1851 {
1852 buf[i]=unpackbuf[i];
1853
1854 if(!is_in_selection(i&0x0F, (i&0xF0)>>4))
1855 continue;
1856
1857 if(ignore_transparent)
1858 {
1859 if(buf[i]==0)
1860 continue;
1861
1862 buf[i]=wrap(buf[i]+amount, 1, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1863 }
1864 else // Don't ignore transparent
1865 buf[i]=wrap(buf[i]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1866 }
1867
1868 pack_tile(newtilebuf,buf,tile);
1869 }
1870
1871 void clear_selection_grid()
1872 {
1873 unfloat_selection();
1874 for(int32_t x=0; x<18; ++x)
1875 {
1876 for(int32_t y=0; y<18; ++y)
1877 {
1878 selection_grid[x][y]=0;
1879 }
1880 }
1881 }
1882
1883 void invert_selection_grid()
1884 {
1885 unfloat_selection();
1886 for(int32_t x=1; x<17; ++x)
1887 {
1888 for(int32_t y=1; y<17; ++y)
1889 {
1890 selection_grid[x][y]=selection_grid[x][y]?0:1;
1891 }
1892 }
1893 }
1894
1895 void shift_selection_grid(int32_t xoffs, int32_t yoffs)
1896 {
1897 byte local_grid[16][16];
1898 memset(local_grid, 0, sizeof(local_grid));
1899 for(auto x = 0; x < 16; ++x)
1900 {
1901 for(auto y = 0; y < 16; ++y)
1902 {
1903 auto offs_x = (x+xoffs)%16, offs_y = (y+yoffs)%16;
1904 if(offs_x < 0) offs_x = (16 - abs(offs_x));
1905 if(offs_y < 0) offs_y = (16 - abs(offs_y));
1906 local_grid[offs_x][offs_y] = selection_grid[x+1][y+1]?1:0;
1907 }
1908 }
1909 for(auto x = 0; x < 16; ++x)
1910 {
1911 for(auto y = 0; y < 16; ++y)
1912 {
1913 selection_grid[x+1][y+1] = local_grid[x][y]?1:0;
1914 }
1915 }
1916 }
1917
1918 void show_edit_tile_help()
1919 {
1920 InfoDialog("Help: Tile Editor", "Hotkeys:"
1921 "\nF1: This Help Dialog"
1922 "\nEnter: Unfloat Sel / OK | Esc: Unfloat Sel / Cancel"
1923 "\nDelete: Clear Tile/Sel | Ctrl+Delete: Clear Tile"
1924 "\nA: Sel All | D: Unselect Sel | I: Invert Sel"
1925 "\nH/V: Flip | (Shift+)R: Rotate"
1926 "\n+/-: Change CSet | Ctrl +/-: Shift Colors"
1927 "\n(Ctrl+)S: Swap Colors | U/Ctrl+Z: Undo"
1928 "\nF12: Screenshot (whole screen)"
1929 "\nArrows: Shift Pixel | Ctrl+Arrows: Change Tile"
1930 "\nWhen not on Select tools, hold to swap:"
1931 "\nCtrl - Fill | Alt - Grab | Ctrl+Alt - Recolor").show();
1932 }
1933
1934 static int move_origin_x=-1, move_origin_y=-1;
1935 static int prev_x=-1, prev_y=-1;
1936 bool __pixel_draw(int x, int y, int tile, int flip)
1937 {
1938 bool ret = false;
1939 switch(tool)
1940 {
1941 case t_pen:
1942 if(flip&1) x=15-x;
1943
1944 if(flip&2) y=15-y;
1945
1946 if(is_in_selection(x,y))
1947 {
1948 if(floating_sel)
1949 {
1950 floatsel[(y<<4)+x]=(drawing==1)?c1:c2;
1951 }
1952 else
1953 {
1954 unpack_tile(newtilebuf, tile, 0, false);
1955 unpackbuf[((y<<4)+x)]=(drawing==1)?c1:c2;
1956 pack_tile(newtilebuf, unpackbuf,tile);
1957 }
1958 }
1959 break;
1960
1961 case t_fill:
1962 if(is_in_selection(x,y))
1963 {
1964 tile_floodfill(tile,x,y,(drawing==1)?c1:c2);
1965 ret = true;
1966 }
1967 break;
1968
1969 case t_recolor:
1970 if(is_in_selection(x,y))
1971 {
1972 if(floating_sel)
1973 {
1974 tf_u = floatsel[(y<<4)+x];
1975 for(int32_t i=0; i<256; i++)
1976 {
1977 if(is_in_selection(i&15,i>>4))
1978 {
1979 if(floatsel[i]==tf_u)
1980 {
1981 floatsel[i]=(drawing==1)?c1:c2;
1982 }
1983 }
1984 }
1985 }
1986 else
1987 {
1988 unpack_tile(newtilebuf, tile, 0, false);
1989 tf_u = unpackbuf[(y<<4)+x];
1990 if(tf_u != ((drawing==1)?c1:c2))
1991 {
1992 for(int32_t i=0; i<256; i++)
1993 {
1994 if(is_in_selection(i&15,i>>4))
1995 {
1996 if(unpackbuf[i]==tf_u)
1997 {
1998 unpackbuf[i]=(drawing==1)?c1:c2;
1999 }
2000 }
2001 }
2002
2003 pack_tile(newtilebuf, unpackbuf,tile);
2004 }
2005 }
2006 ret = true;
2007 }
2008 break;
2009
2010 case t_eyedropper:
2011 if(floating_sel)
2012 memcpy(unpackbuf, floatsel, 256);
2013 else unpack_tile(newtilebuf, tile, 0, false);
2014
2015 if(gui_mouse_b()&1)
2016 {
2017 c1=unpackbuf[((y<<4)+x)];
2018 }
2019
2020 if(gui_mouse_b()&2)
2021 {
2022 c2=unpackbuf[((y<<4)+x)];
2023 }
2024 break;
2025
2026 case t_move:
2027 if((prev_x!=x)||(prev_y!=y))
2028 {
2029 if(has_selection())
2030 {
2031 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2032 wrap_sel_tile(y-prev_y, x-prev_x);
2033 shift_selection_grid(x-prev_x, y-prev_y);
2034 }
2035 else wrap_tile(tile, y-move_origin_y, x-move_origin_x, drawing==2);
2036 prev_x=x;
2037 prev_y=y;
2038 }
2039 break;
2040
2041 case t_select:
2042 unfloat_selection();
2043 if(flip&1) x=15-x;
2044
2045 if(flip&2) y=15-y;
2046
2047 if(selecting_x1==-1||selecting_y1==-1)
2048 {
2049 selecting_x1=x;
2050 selecting_y1=y;
2051 }
2052 else
2053 {
2054 selecting_x2=x;
2055 selecting_y2=y;
2056 }
2057 break;
2058
2059 case t_wand:
2060 unfloat_selection();
2061 if(flip&1) x=15-x;
2062
2063 if(flip&2) y=15-y;
2064
2065 switch(select_mode)
2066 {
2067 case 0:
2068 clear_selection_grid();
2069 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2070 break;
2071
2072 case 1:
2073 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2074 break;
2075
2076 case 2:
2077 remove_color_from_selection(unpackbuf[((y<<4)+x)]);
2078 break;
2079
2080 case 3:
2081 intersect_color_with_selection(unpackbuf[((y<<4)+x)]);
2082 break;
2083 }
2084
2085 ret = true;
2086 break;
2087 }
2088 return ret;
2089 }
2090 void edit_tile(int32_t tile,int32_t flip,int32_t &cs)
2091 {
2092 popup_zqdialog_start();
2093 FONT* oldfont = font;
2094 font = get_custom_font(CFONT_DLG);
2095 edit_button.h = ok_button.h = cancel_button.h = 12+text_height(font);
2096 status_info.yscale = text_height(font);
2097 status_info.y = 308-(status_info.h*status_info.yscale);
2098 hover_info.yscale = status_info.yscale;
2099 hover_info.y = 338-(hover_info.h*hover_info.yscale);
2100 go();
2101 undocount = tilesize(newtilebuf[tile].format);
2102 clear_selection_grid();
2103 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2104
2105 tthighlight = zc_get_config("ZQ_GUI","tile_edit_fancyhighlight",1);
2106 showcolortip = zc_get_config("ZQ_GUI","tile_edit_colornames",1);
2107
2108 PALETTE tpal;
2109 byte oldtile[256];
2110
2111 memset(&tpal, 0, sizeof(PALETTE));
2112 memset(oldtile, 0, 256);
2113
2114 for(int32_t i=0; i<undocount; i++)
2115 {
2116 oldtile[i]=undotile[i]=newtilebuf[tile].data[i];
2117 }
2118 byte undoselgrid[16][16];
2119 for(auto x = 0; x < 16; ++x)
2120 for(auto y = 0; y < 16; ++y)
2121 undoselgrid[x][y] = selection_grid[x+1][y+1];
2122 for(auto q = 0; q < 256; ++q)
2123 {
2124 floatsel[q] = 0;
2125 undofloatsel[q] = 0;
2126 floating_sel = false;
2127 undo_is_floatsel = false;
2128 }
2129
2130 int32_t tile_x=-1, tile_y=-1;
2131 int32_t temp_x=-1, temp_y=-1;
2132 bool bdown=false;
2133 int32_t done=0;
2134 drawing=0;
2135 tool_cur = -1;
2136
2137 get_palette(tpal);
2138
2139 if(newtilebuf[tile].format==tf4Bit)
2140 {
2141 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2142 }
2143 else
2144 {
2145 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2146 }
2147
2148 custom_vsync();
2149 zc_set_palette(tpal);
2150 draw_edit_scr(tile,flip,cs,oldtile, true);
2151
2152 while(gui_mouse_b())
2153 {
2154 /* do nothing */
2155 rest(1);
2156 }
2157
2158 move_origin_x=-1;
2159 move_origin_y=-1;
2160 prev_x=-1;
2161 prev_y=-1;
2162
2163
2164
2165 byte selection_pattern_source[8][8]=
2166 {
2167 {1, 1, 1, 1, 0, 0, 0, 0},
2168 {1, 1, 1, 0, 0, 0, 0, 1},
2169 {1, 1, 0, 0, 0, 0, 1, 1},
2170 {1, 0, 0, 0, 0, 1, 1, 1},
2171 {0, 0, 0, 0, 1, 1, 1, 1},
2172 {0, 0, 0, 1, 1, 1, 1, 0},
2173 {0, 0, 1, 1, 1, 1, 0, 0},
2174 {0, 1, 1, 1, 1, 0, 0, 0},
2175 };
2176
2177 byte selecting_pattern_source[8][8]=
2178 {
2179 {1, 1, 0, 0, 0, 0, 1, 1},
2180 {1, 0, 0, 0, 0, 1, 1, 1},
2181 {0, 0, 0, 0, 1, 1, 1, 1},
2182 {0, 0, 0, 1, 1, 1, 1, 0},
2183 {0, 0, 1, 1, 1, 1, 0, 0},
2184 {0, 1, 1, 1, 1, 0, 0, 0},
2185 {1, 1, 1, 1, 0, 0, 0, 0},
2186 {1, 1, 1, 0, 0, 0, 0, 1},
2187 };
2188
2189 byte intersection_pattern_source[8][8]=
2190 {
2191 {0, 0, 1, 1, 0, 0, 1, 1},
2192 {0, 1, 1, 0, 0, 1, 1, 0},
2193 {1, 1, 0, 0, 1, 1, 0, 0},
2194 {1, 0, 0, 1, 1, 0, 0, 1},
2195 {0, 0, 1, 1, 0, 0, 1, 1},
2196 {0, 1, 1, 0, 0, 1, 1, 0},
2197 {1, 1, 0, 0, 1, 1, 0, 0},
2198 {1, 0, 0, 1, 1, 0, 0, 1},
2199 };
2200
2201 selection_pattern=create_bitmap_ex(8, 8, 8);
2202
2203 for(int32_t x=0; x<8; ++x)
2204 {
2205 for(int32_t y=0; y<8; ++y)
2206 {
2207 selection_pattern->line[y][x]=selection_pattern_source[x][y]?vc(0):vc(15);
2208 }
2209 }
2210
2211 selecting_pattern=create_bitmap_ex(8, 8, 8);
2212
2213 for(int32_t x=0; x<8; ++x)
2214 {
2215 for(int32_t y=0; y<8; ++y)
2216 {
2217 selecting_pattern->line[y][x]=selecting_pattern_source[x][y]?vc(0):vc(15);
2218 }
2219 }
2220
2221 intersection_pattern=create_bitmap_ex(8, 8, 8);
2222
2223 for(int32_t x=0; x<8; ++x)
2224 {
2225 for(int32_t y=0; y<8; ++y)
2226 {
2227 intersection_pattern->line[y][x]=intersection_pattern_source[x][y]?vc(0):vc(15);
2228 }
2229 }
2230
2231 do
2232 {
2233 HANDLE_CLOSE_ZQDLG();
2234 if(exiting_program) break;
2235 int32_t temp_mouse_x=gui_mouse_x();
2236 int32_t temp_mouse_y=gui_mouse_y();
2237 rest(4);
2238 bool redraw=false;
2239 bool did_wand_select=false;
2240
2241 if(keypressed())
2242 {
2243 bool ctrl = CHECK_CTRL_CMD;
2244 int k = readkey()>>8;
2245 switch(k)
2246 {
2247 case KEY_F1:
2248 show_edit_tile_help();
2249 break;
2250 case KEY_ENTER_PAD:
2251 case KEY_ENTER:
2252 if(floating_sel)
2253 unfloat_selection();
2254 else done=2;
2255 break;
2256
2257 case KEY_ESC:
2258 if(floating_sel)
2259 unfloat_selection();
2260 else if(has_selection())
2261 clear_selection_grid();
2262 else done=1;
2263 break;
2264
2265 case KEY_DEL:
2266 {
2267 unpack_tile(newtilebuf, tile, 0, false);
2268 bool all = CHECK_CTRL_CMD || !has_selection();
2269 bool canDel = false;
2270 if(all)
2271 {
2272 //Check all
2273 for(auto q = 0; q < 256; ++q)
2274 if(unpackbuf[q])
2275 {
2276 canDel = true;
2277 break;
2278 }
2279 }
2280 else
2281 {
2282 //Check selection
2283 for(auto x = 0; x < 16; ++x)
2284 for(auto y = 0; y < 16; ++y)
2285 if(is_in_selection(x,y))
2286 if(unpackbuf[(y<<4)+x])
2287 {
2288 canDel = true;
2289 break;
2290 }
2291 }
2292 if(!canDel) break; //don't delete (and thus reset undo) if nothing would change!
2293
2294 for(int32_t i=0; i<undocount; i++)
2295 {
2296 undotile[i]=newtilebuf[tile].data[i];
2297 }
2298 for(auto x = 0; x < 16; ++x)
2299 for(auto y = 0; y < 16; ++y)
2300 undoselgrid[x][y] = selection_grid[x+1][y+1];
2301 for(auto q = 0; q < 256; ++q)
2302 undofloatsel[q] = floatsel[q];
2303 undo_is_floatsel = floating_sel;
2304
2305 if(CHECK_CTRL_CMD || !has_selection())
2306 {
2307 //Delete all
2308 for(auto q = 0; q < 256; ++q)
2309 {
2310 unpackbuf[q] = 0;
2311 floatsel[q] = 0;
2312 }
2313 }
2314 else
2315 {
2316 //Delete selection
2317 for(auto x = 0; x < 16; ++x)
2318 for(auto y = 0; y < 16; ++y)
2319 {
2320 if(floating_sel)
2321 {
2322 floatsel[x+(y<<4)] = 0;
2323 }
2324 else if(is_in_selection(x,y))
2325 {
2326 unpackbuf[(y<<4)+x] = 0;
2327 }
2328 }
2329 }
2330 pack_tile(newtilebuf, unpackbuf, tile);
2331 redraw=true;
2332 }
2333 break;
2334
2335 case KEY_A:
2336 clear_selection_grid();
2337 invert_selection_grid();
2338 redraw=true;
2339 break;
2340
2341 case KEY_D:
2342 clear_selection_grid();
2343 redraw=true;
2344 break;
2345
2346 case KEY_I:
2347 invert_selection_grid();
2348 redraw=true;
2349 break;
2350
2351 case KEY_H:
2352 flip^=1;
2353 normalize(tile,tile,0,flip);
2354 flip=0;
2355 redraw=true;
2356 break;
2357
2358 case KEY_V:
2359 flip^=2;
2360 normalize(tile,tile,0,flip);
2361 flip=0;
2362 redraw=true;
2363 break;
2364
2365 case KEY_F12:
2366 onSnapshot();
2367 break;
2368
2369 case KEY_R:
2370 {
2371 //if(CHECK_CTRL_CMD))
2372 // {
2373 //do_recolor(tile); redraw=true; saved=false;
2374 // }
2375 //else
2376 // {
2377 go_tiles();
2378 rotate_tile(tile,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
2379 redraw=true;
2380 saved=false;
2381 break;
2382 }
2383
2384 case KEY_EQUALS:
2385 case KEY_PLUS_PAD:
2386 {
2387 if(CHECK_CTRL_CMD ||
2388 key[KEY_ALT] || key[KEY_ALTGR])
2389 {
2390 for(int32_t i=0; i<undocount; i++)
2391 undotile[i]=newtilebuf[tile].data[i];
2392 for(auto x = 0; x < 16; ++x)
2393 for(auto y = 0; y < 16; ++y)
2394 undoselgrid[x][y] = selection_grid[x+1][y+1];
2395 for(auto q = 0; q < 256; ++q)
2396 undofloatsel[q] = floatsel[q];
2397 undo_is_floatsel = floating_sel;
2398
2399 if(key[KEY_ALT] || key[KEY_ALTGR])
2400 shift_tile_colors(tile, 16, false);
2401 else
2402 shift_tile_colors(tile, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2403 }
2404 else
2405 cs = (cs<13) ? cs+1:0;
2406
2407 redraw=true;
2408 break;
2409 }
2410
2411 case KEY_MINUS:
2412 case KEY_MINUS_PAD:
2413 {
2414 if(CHECK_CTRL_CMD ||
2415 key[KEY_ALT] || key[KEY_ALTGR])
2416 {
2417 for(int32_t i=0; i<undocount; i++)
2418 undotile[i]=newtilebuf[tile].data[i];
2419 for(auto x = 0; x < 16; ++x)
2420 for(auto y = 0; y < 16; ++y)
2421 undoselgrid[x][y] = selection_grid[x+1][y+1];
2422 for(auto q = 0; q < 256; ++q)
2423 undofloatsel[q] = floatsel[q];
2424 undo_is_floatsel = floating_sel;
2425
2426 if(key[KEY_ALT] || key[KEY_ALTGR])
2427 shift_tile_colors(tile, -16, false);
2428 else
2429 shift_tile_colors(tile, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2430 }
2431 else
2432 cs = (cs>0) ? cs-1:13;
2433
2434 redraw=true;
2435 break;
2436 }
2437
2438 case KEY_SPACE:
2439 gridmode=(gridmode+1)%gm_max;
2440 redraw=true;
2441 break;
2442
2443 case KEY_Z:
2444 if(!ctrl)
2445 break;
2446 //Ctrl+Z == undo
2447 [[fallthrough]];
2448 case KEY_U:
2449 for(int32_t i=0; i<undocount; i++)
2450 zc_swap(undotile[i],newtilebuf[tile].data[i]);
2451
2452 for(auto x = 0; x < 16; ++x)
2453 for(auto y = 0; y < 16; ++y)
2454 zc_swap(selection_grid[x+1][y+1], undoselgrid[x][y]);
2455
2456 for(auto q = 0; q < 256; ++q)
2457 zc_swap(undofloatsel[q], floatsel[q]);
2458 zc_swap(undo_is_floatsel, floating_sel);
2459
2460 redraw=true;
2461 break;
2462
2463 case KEY_S:
2464 if(CHECK_CTRL_CMD)
2465 {
2466 for(int32_t i=0; i<undocount; i++)
2467 {
2468 undotile[i]=newtilebuf[tile].data[i];
2469 }
2470 for(auto x = 0; x < 16; ++x)
2471 for(auto y = 0; y < 16; ++y)
2472 undoselgrid[x][y] = selection_grid[x+1][y+1];
2473 for(auto q = 0; q < 256; ++q)
2474 undofloatsel[q] = floatsel[q];
2475 undo_is_floatsel = floating_sel;
2476
2477 unpack_tile(newtilebuf, tile, 0, false);
2478
2479 if(has_selection())
2480 {
2481 for(int32_t i=0; i<256; i++)
2482 {
2483 if(!is_in_selection(i%16,i/16))
2484 continue;
2485 if(unpackbuf[i]==c1)
2486 {
2487 unpackbuf[i]=c2;
2488 }
2489 else if(unpackbuf[i]==c2)
2490 {
2491 unpackbuf[i]=c1;
2492 }
2493 if(floating_sel)
2494 {
2495 if(floatsel[i]==c1)
2496 {
2497 floatsel[i]=c2;
2498 }
2499 else if(floatsel[i]==c2)
2500 {
2501 floatsel[i]=c1;
2502 }
2503 }
2504 }
2505 }
2506 else
2507 {
2508 for(int32_t i=0; i<256; i++)
2509 {
2510 if(unpackbuf[i]==c1)
2511 {
2512 unpackbuf[i]=c2;
2513 }
2514 else if(unpackbuf[i]==c2)
2515 {
2516 unpackbuf[i]=c1;
2517 }
2518 }
2519 }
2520
2521 pack_tile(newtilebuf, unpackbuf,tile);
2522 }
2523
2524 zc_swap(c1,c2);
2525 redraw=true;
2526 break;
2527
2528 case KEY_UP:
2529 if(CHECK_CTRL_CMD)
2530 {
2531 unfloat_selection();
2532 tile=zc_max(0,tile-TILES_PER_ROW);
2533 undocount = tilesize(newtilebuf[tile].format);
2534
2535 for(int32_t i=0; i<undocount; i++)
2536 {
2537 undotile[i]=newtilebuf[tile].data[i];
2538 oldtile[i]=undotile[i];
2539 }
2540
2541 redraw=true;
2542 }
2543 else
2544 {
2545 for(int32_t i=0; i<undocount; i++)
2546 {
2547 undotile[i]=newtilebuf[tile].data[i];
2548 }
2549 for(auto x = 0; x < 16; ++x)
2550 for(auto y = 0; y < 16; ++y)
2551 undoselgrid[x][y] = selection_grid[x+1][y+1];
2552 for(auto q = 0; q < 256; ++q)
2553 undofloatsel[q] = floatsel[q];
2554 undo_is_floatsel = floating_sel;
2555 if(has_selection())
2556 {
2557 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2558 wrap_sel_tile(-1, 0);
2559 shift_selection_grid(0, -1);
2560 }
2561 else wrap_tile(tile, -1, 0, false);
2562 redraw=true;
2563 }
2564 break;
2565
2566 case KEY_DOWN:
2567 if(CHECK_CTRL_CMD)
2568 {
2569 unfloat_selection();
2570 tile=zc_min(tile+TILES_PER_ROW,NEWMAXTILES-1);
2571 undocount = tilesize(newtilebuf[tile].format);
2572
2573 for(int32_t i=0; i<undocount; i++)
2574 {
2575 undotile[i]=newtilebuf[tile].data[i];
2576 oldtile[i]=undotile[i];
2577 }
2578
2579 redraw=true;
2580 }
2581 else
2582 {
2583 for(int32_t i=0; i<undocount; i++)
2584 {
2585 undotile[i]=newtilebuf[tile].data[i];
2586 }
2587 for(auto x = 0; x < 16; ++x)
2588 for(auto y = 0; y < 16; ++y)
2589 undoselgrid[x][y] = selection_grid[x+1][y+1];
2590 for(auto q = 0; q < 256; ++q)
2591 undofloatsel[q] = floatsel[q];
2592 undo_is_floatsel = floating_sel;
2593 if(has_selection())
2594 {
2595 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2596 wrap_sel_tile(1, 0);
2597 shift_selection_grid(0, 1);
2598 }
2599 else wrap_tile(tile, 1, 0, false);
2600 redraw=true;
2601 }
2602 break;
2603
2604 case KEY_LEFT:
2605 if(CHECK_CTRL_CMD)
2606 {
2607 unfloat_selection();
2608 tile=zc_max(0,tile-1);
2609 undocount = tilesize(newtilebuf[tile].format);
2610
2611 for(int32_t i=0; i<undocount; i++)
2612 {
2613 undotile[i]=newtilebuf[tile].data[i];
2614 oldtile[i]=undotile[i];
2615 }
2616
2617 redraw=true;
2618 }
2619 else
2620 {
2621 for(int32_t i=0; i<undocount; i++)
2622 {
2623 undotile[i]=newtilebuf[tile].data[i];
2624 }
2625 for(auto x = 0; x < 16; ++x)
2626 for(auto y = 0; y < 16; ++y)
2627 undoselgrid[x][y] = selection_grid[x+1][y+1];
2628 for(auto q = 0; q < 256; ++q)
2629 undofloatsel[q] = floatsel[q];
2630 undo_is_floatsel = floating_sel;
2631 if(has_selection())
2632 {
2633 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2634 wrap_sel_tile(0, -1);
2635 shift_selection_grid(-1, 0);
2636 }
2637 else wrap_tile(tile, 0, -1, false);
2638 redraw=true;
2639 }
2640 break;
2641
2642 case KEY_RIGHT:
2643 if(CHECK_CTRL_CMD)
2644 {
2645 unfloat_selection();
2646 tile=zc_min(tile+1, NEWMAXTILES-1);
2647 undocount = tilesize(newtilebuf[tile].format);
2648
2649 for(int32_t i=0; i<undocount; i++)
2650 {
2651 undotile[i]=newtilebuf[tile].data[i];
2652 oldtile[i]=undotile[i];
2653 }
2654
2655 redraw=true;
2656 }
2657 else
2658 {
2659 for(int32_t i=0; i<undocount; i++)
2660 {
2661 undotile[i]=newtilebuf[tile].data[i];
2662 }
2663 for(auto x = 0; x < 16; ++x)
2664 for(auto y = 0; y < 16; ++y)
2665 undoselgrid[x][y] = selection_grid[x+1][y+1];
2666 for(auto q = 0; q < 256; ++q)
2667 undofloatsel[q] = floatsel[q];
2668 undo_is_floatsel = floating_sel;
2669 if(has_selection())
2670 {
2671 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2672 wrap_sel_tile(0, 1);
2673 shift_selection_grid(1, 0);
2674 }
2675 else wrap_tile(tile, 0, 1, false);
2676 redraw=true;
2677 }
2678 break;
2679 case KEY_0: case KEY_1: case KEY_2: case KEY_3:
2680 case KEY_4: case KEY_5: case KEY_6: case KEY_7:
2681 case KEY_8: case KEY_9:
2682 case KEY_0_PAD: case KEY_1_PAD: case KEY_2_PAD: case KEY_3_PAD:
2683 case KEY_4_PAD: case KEY_5_PAD: case KEY_6_PAD: case KEY_7_PAD:
2684 case KEY_8_PAD: case KEY_9_PAD:
2685 {
2686 int t = k - ((k>KEY_9) ? KEY_1_PAD : KEY_1);
2687 if(unsigned(t) < t_max)
2688 {
2689 if(old_tool != -1)
2690 old_tool = t;
2691 else tool = t;
2692 }
2693 break;
2694 }
2695 case KEY_TAB:
2696 {
2697 if(key_shifts & KB_CTRL_CMD_FLAG)
2698 {
2699 xmode = (xmode+1)%XMODE_MAX;
2700 if(!xmode)
2701 bgmode = (bgmode+1)%BGMODE_MAX;
2702 }
2703 else if(key_shifts & KB_SHIFT_FLAG)
2704 hide_grid = !hide_grid;
2705 else show_quartgrid = !show_quartgrid;
2706 redraw = true;
2707 break;
2708 }
2709 }
2710 clear_keybuf();
2711 }
2712
2713 if(!gui_mouse_b())
2714 {
2715 if(is_selecting())
2716 {
2717 unfloat_selection();
2718 int32_t x1=zc_min(selecting_x1,selecting_x2);
2719 int32_t x2=zc_max(selecting_x1,selecting_x2);
2720 int32_t y1=zc_min(selecting_y1,selecting_y2);
2721 int32_t y2=zc_max(selecting_y1,selecting_y2);
2722
2723 if(select_mode==0)
2724 {
2725 clear_selection_grid();
2726 }
2727
2728 for(int32_t x=x1; x<=x2; ++x)
2729 {
2730 for(int32_t y=y1; y<=y2; ++y)
2731 {
2732 selection_grid[x+1][y+1]=((select_mode<2)?(1):(((select_mode==2)?(0):(selection_grid[x+1][y+1]))));
2733 }
2734 }
2735
2736 if(select_mode==3)
2737 {
2738 for(int32_t y=0; y<16; ++y)
2739 {
2740 for(int32_t x=0; x<x1; ++x)
2741 {
2742 selection_grid[x+1][y+1]=0;
2743 }
2744
2745 for(int32_t x=x2+1; x<16; ++x)
2746 {
2747 selection_grid[x+1][y+1]=0;
2748 }
2749 }
2750
2751 for(int32_t x=x1; x<=x2; ++x)
2752 {
2753 for(int32_t y=0; y<y1; ++y)
2754 {
2755 selection_grid[x+1][y+1]=0;
2756 }
2757
2758 for(int32_t y=y2+1; y<16; ++y)
2759 {
2760 selection_grid[x+1][y+1]=0;
2761 }
2762 }
2763 }
2764 }
2765
2766 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2767 did_wand_select=false;
2768 }
2769
2770 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
2771 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2772 bool ctrl=CHECK_CTRL_CMD;
2773 static int32_t last_tool_val = 0;
2774
2775 if(tool==t_select||tool==t_wand)
2776 {
2777 if(!drawing)
2778 {
2779 int32_t type=0;
2780
2781 if(has_selection())
2782 {
2783 if(shift)
2784 {
2785 type+=1;
2786 }
2787
2788 if(alt)
2789 {
2790 type+=2;
2791 }
2792 }
2793
2794 if(type!=select_mode)
2795 {
2796 select_mode=type;
2797
2798 if(isinRect(temp_mouse_x,temp_mouse_y-(tool==t_fill ? (14) : 0),zoomtile.x,zoomtile.y,zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2799 set_tool_sprite(tool,type);
2800 }
2801 }
2802 }
2803 else if(alt||ctrl)
2804 {
2805 if(old_tool==-1)
2806 {
2807 old_tool = tool;
2808 tool_cur = -1;
2809 }
2810 if(alt&&ctrl)
2811 tool = t_recolor;
2812 else if(alt)
2813 tool = t_eyedropper;
2814 else tool = t_fill;
2815 }
2816 else if(old_tool!=-1)
2817 {
2818 tool = old_tool;
2819 old_tool = -1;
2820 tool_cur = -1;
2821 redraw = true;
2822 }
2823 if(last_tool_val != tool)
2824 {
2825 redraw = true;
2826 tool_cur = -1;
2827 update_tool_cursor();
2828 last_tool_val = tool;
2829 }
2830
2831 if(!bdown)
2832 {
2833 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2834 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2835 }
2836
2837 if(gui_mouse_b()==1 && !bdown) //pressed the left mouse button
2838 {
2839 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2840 {
2841 if(tool==t_move || tool==t_fill)
2842 {
2843 set_tool_sprite(tool,1);
2844
2845 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2846 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2847 }
2848
2849 for(int32_t i=0; i<undocount; i++)
2850 {
2851 undotile[i]=newtilebuf[tile].data[i];
2852 }
2853 for(auto x = 0; x < 16; ++x)
2854 for(auto y = 0; y < 16; ++y)
2855 undoselgrid[x][y] = selection_grid[x+1][y+1];
2856 for(auto q = 0; q < 256; ++q)
2857 undofloatsel[q] = floatsel[q];
2858 undo_is_floatsel = floating_sel;
2859
2860 drawing=1;
2861 }
2862
2863 if(ok_button.rect(temp_mouse_x,temp_mouse_y))
2864 {
2865 if(do_text_button(ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK"))
2866 {
2867 done=2;
2868 }
2869 }
2870
2871 if(cancel_button.rect(temp_mouse_x,temp_mouse_y))
2872 {
2873 if(do_text_button(cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel"))
2874 {
2875 done=1;
2876 }
2877 }
2878
2879 if(edit_button.rect(temp_mouse_x,temp_mouse_y))
2880 {
2881 if(do_text_button(edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal"))
2882 {
2883 colors_menu.pop(edit_button.x+2,edit_button.y-40);
2884 get_palette(tpal);
2885
2886 if(newtilebuf[tile].format==tf4Bit)
2887 {
2888 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2889 }
2890 else
2891 {
2892 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2893 }
2894
2895 redraw=true;
2896 }
2897 }
2898
2899 int sqr_clicked;
2900 if(show_quartgrid && qgrid_tool(tool))
2901 {
2902 sqr_clicked = reflbtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2903 if(sqr_clicked > -1)
2904 {
2905 auto& sqr = reflbtn_grid.subsquare(sqr_clicked);
2906 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[sqr_clicked]))
2907 refl_flags ^= (1<<sqr_clicked);
2908 }
2909 }
2910 sqr_clicked = xmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2911 if(sqr_clicked > -1)
2912 {
2913 auto& sqr = xmodebtn_grid.subsquare(sqr_clicked);
2914 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[sqr_clicked]))
2915 xmode = sqr_clicked;
2916 }
2917 sqr_clicked = bgmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2918 if(sqr_clicked > -1)
2919 {
2920 auto& sqr = bgmodebtn_grid.subsquare(sqr_clicked);
2921 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[sqr_clicked]))
2922 bgmode = sqr_clicked;
2923 }
2924
2925 if(showcolortip)
2926 {
2927 auto oy = color_info.y;
2928 if(reftile <= 0)
2929 color_info.y -= ref_til.h + 8;
2930 if(color_info.rect(temp_mouse_x,temp_mouse_y))
2931 {
2932 showcolortip = 0;
2933 zc_set_config("ZQ_GUI","tile_edit_colornames",0);
2934 }
2935 color_info.y = oy;
2936 }
2937 else
2938 {
2939 auto oy = color_info_btn.y;
2940 if(reftile <= 0)
2941 color_info_btn.y -= ref_til.h + 8;
2942 if(color_info_btn.rect(temp_mouse_x,temp_mouse_y))
2943 {
2944 if(do_text_button(color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,"Show Colors"))
2945 {
2946 showcolortip = 1;
2947 zc_set_config("ZQ_GUI","tile_edit_colornames",1);
2948 redraw=true;
2949 }
2950 }
2951 color_info_btn.y = oy;
2952 }
2953
2954 if(hlcbox.rect(temp_mouse_x,temp_mouse_y))
2955 {
2956 if(do_checkbox(screen2,hlcbox.x,hlcbox.y,hlcbox.w,hlcbox.h,tthighlight))
2957 {
2958 zc_set_config("ZQ_GUI","tile_edit_fancyhighlight",tthighlight);
2959 redraw=true;
2960 }
2961 }
2962 if(quartgrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2963 {
2964 if(do_checkbox(screen2,quartgrid_cbox.x,quartgrid_cbox.y,quartgrid_cbox.w,quartgrid_cbox.h,show_quartgrid))
2965 redraw=true;
2966 }
2967 if(hidegrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2968 {
2969 if(do_checkbox(screen2,hidegrid_cbox.x,hidegrid_cbox.y,hidegrid_cbox.w,hidegrid_cbox.h,hide_grid))
2970 redraw=true;
2971 }
2972
2973 switch(newtilebuf[tile].format)
2974 {
2975 case tf4Bit:
2976 {
2977 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
2978 if(ind > -1)
2979 {
2980 c1 = ind;
2981 redraw=true;
2982 }
2983 break;
2984 }
2985 case tf8Bit:
2986 {
2987 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
2988 if(ind > -1)
2989 {
2990 c1 = ind;
2991 redraw=true;
2992 }
2993 break;
2994 }
2995 }
2996
2997
2998 int32_t newtool = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
2999 if(newtool > -1 && newtool < t_max)
3000 {
3001 tool=newtool;
3002 redraw=true;
3003 }
3004
3005 if(x_btn.rect(temp_mouse_x,temp_mouse_y))
3006 {
3007 if(do_x_button(screen, x_btn.x, x_btn.y))
3008 {
3009 done=1;
3010 }
3011 }
3012 if(info_btn.rect(temp_mouse_x,temp_mouse_y))
3013 {
3014 if(do_question_button(screen, info_btn.x, info_btn.y))
3015 {
3016 show_edit_tile_help();
3017 }
3018 }
3019
3020 bdown=true;
3021 }
3022
3023 if(gui_mouse_b()&2 && !bdown) //pressed the right mouse button
3024 {
3025 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3026 {
3027 if(tool==t_move || tool==t_fill)
3028 {
3029 set_tool_sprite(tool,1);
3030
3031 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
3032 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
3033 }
3034
3035 for(int32_t i=0; i<undocount; i++)
3036 {
3037 undotile[i]=newtilebuf[tile].data[i];
3038 }
3039 for(auto x = 0; x < 16; ++x)
3040 for(auto y = 0; y < 16; ++y)
3041 undoselgrid[x][y] = selection_grid[x+1][y+1];
3042 for(auto q = 0; q < 256; ++q)
3043 undofloatsel[q] = floatsel[q];
3044 undo_is_floatsel = floating_sel;
3045
3046 drawing=2;
3047 }
3048
3049 switch(newtilebuf[tile].format)
3050 {
3051 case tf4Bit:
3052 {
3053 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
3054 if(ind > -1)
3055 {
3056 c2 = ind;
3057 redraw=true;
3058 }
3059 break;
3060 }
3061 case tf8Bit:
3062 {
3063 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
3064 if(ind > -1)
3065 {
3066 c2 = ind;
3067 redraw=true;
3068 }
3069 break;
3070 }
3071 }
3072
3073 bdown=true;
3074 }
3075
3076 if(bdown&&!gui_mouse_b()) //released the buttons
3077 {
3078 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3079 {
3080 if(tool==t_move || tool==t_fill)
3081 {
3082 set_tool_sprite(tool,0);
3083 }
3084 }
3085 }
3086
3087 if(drawing && zoomtile.rect(temp_mouse_x,temp_mouse_y)) //inside the zoomed tile window
3088 {
3089 int32_t ind = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3090 int32_t x=ind%zoomtile.w;
3091 int32_t y=ind/zoomtile.w;
3092
3093 bool reset_draw = false;
3094
3095 if(__pixel_draw(x,y,tile,flip))
3096 reset_draw = true;
3097 if(show_quartgrid)
3098 {
3099 auto tmp_sel_mode = select_mode;
3100 if(tool == t_wand && select_mode == 0)
3101 select_mode = 1;
3102 if(qgrid_tool(tool))
3103 {
3104 if(refl_flags & (1<<REFL_HFLIP))
3105 if(__pixel_draw(15-x,y,tile,flip))
3106 reset_draw = true;
3107 if(refl_flags & (1<<REFL_VFLIP))
3108 if(__pixel_draw(x,15-y,tile,flip))
3109 reset_draw = true;
3110 //Diagonal flip and 180° rotation are the same!
3111 if(refl_flags & ((1<<REFL_DBLFLIP)|(1<<REFL_180)))
3112 if(__pixel_draw(15-x,15-y,tile,flip))
3113 reset_draw = true;
3114 if(refl_flags & (1<<REFL_90CW))
3115 if(__pixel_draw(15-y,x,tile,flip))
3116 reset_draw = true;
3117 if(refl_flags & (1<<REFL_90CCW))
3118 if(__pixel_draw(y,15-x,tile,flip))
3119 reset_draw = true;
3120 }
3121 select_mode = tmp_sel_mode;
3122 }
3123
3124 if(reset_draw)
3125 drawing = 0;
3126 redraw=true;
3127 }
3128
3129 if(gui_mouse_b()==0)
3130 {
3131 bdown=false;
3132 drawing=0;
3133 }
3134
3135 temp_x=(gui_mouse_x()-zoomtile.x)/zoomtile.xscale;
3136 temp_y=(gui_mouse_y()-zoomtile.y)/zoomtile.yscale;
3137
3138 {
3139 tile_x=temp_x;
3140 tile_y=temp_y;
3141 redraw=true;
3142 }
3143
3144 const char *toolnames[t_max]=
3145 {
3146 "Pen\nDraw Single Pixels", "Fill\nCtrl", "Replace Color\nCtrl+Alt", "Grab Color\nAlt", "Move\nMove Selections", "Select Pixels", "Select Color"
3147 };
3148
3149 int32_t toolbtn = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
3150 if(toolbtn > -1 && toolbtn < t_max)
3151 {
3152 int32_t column = toolbtn%tool_btns.w;
3153 int32_t row = toolbtn/tool_btns.w;
3154
3155 update_tooltip(temp_mouse_x,temp_mouse_y,tool_btns.x+(column*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale, toolnames[toolbtn]);
3156 redraw=true;
3157 }
3158 /* Highlight the hovered pixel? Eh, maybe too much?
3159 int32_t hov_pix = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3160 if(hov_pix > -1)
3161 {
3162 int32_t column = hov_pix%zoomtile.w;
3163 int32_t row = hov_pix/zoomtile.w;
3164
3165 update_tooltip(temp_mouse_x,temp_mouse_y,zoomtile.x+(column*zoomtile.xscale),zoomtile.y+(row*zoomtile.yscale),zoomtile.xscale,zoomtile.yscale, NULL);
3166 redraw=true;
3167 }*/
3168
3169 if(redraw)
3170 {
3171 custom_vsync();
3172 draw_edit_scr(tile,flip,cs,oldtile, false);
3173 }
3174 else
3175 {
3176 bool hs=has_selection();
3177
3178 if(hs)
3179 {
3180 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
3181 }
3182
3183 custom_vsync();
3184
3185 if(hs)
3186 {
3187 // blit(screen2, screen, 79, 31, 79, 31, 129, 129);
3188 blit(screen2, screen, zoomtile.x-1,zoomtile.y-1, zoomtile.x-1,zoomtile.y-1, (zoomtile.w*zoomtile.xscale)+1, (zoomtile.h*zoomtile.yscale)+1);
3189 }
3190
3191 update_tool_cursor();
3192 SCRFIX();
3193 }
3194
3195 }
3196 while(!done);
3197
3198 unfloat_selection();
3199 clear_selection_grid();
3200
3201 while(gui_mouse_b())
3202 {
3203 /* do nothing */
3204 rest(1);
3205 }
3206
3207 if(done==1)
3208 {
3209 for(int32_t i=0; i<undocount; i++)
3210 {
3211 newtilebuf[tile].data[i]=oldtile[i];
3212 }
3213 }
3214 else
3215 {
3216 byte *buf = new byte[undocount];
3217
3218 // put back old tile
3219 for(int32_t i=0; i<undocount; i++)
3220 {
3221 buf[i] = newtilebuf[tile].data[i];
3222 newtilebuf[tile].data[i] = oldtile[i];
3223 }
3224
3225 // go
3226 go_tiles();
3227
3228 // replace old tile with new one again
3229 for(int32_t i=0; i<undocount; i++)
3230 {
3231 newtilebuf[tile].data[i] = buf[i];
3232 }
3233
3234 saved=false;
3235
3236 if(buf!=NULL)
3237 {
3238 delete[] buf;
3239 }
3240 }
3241
3242 MouseSprite::set(ZQM_NORMAL);
3243 register_blank_tiles();
3244 register_used_tiles();
3245 clear_tooltip();
3246 comeback();
3247 destroy_bitmap(selection_pattern);
3248 destroy_bitmap(selecting_pattern);
3249 destroy_bitmap(intersection_pattern);
3250 font = oldfont;
3251 popup_zqdialog_end();
3252 }
3253
3254 /* Grab Tile Code */
3255
3256 enum recolorState { rcNone, rc4Bit, rc8Bit };
3257
3258 BITMAP* original_imagebuf_bitmap=NULL;
3259 void *imagebuf=NULL;
3260 int32_t imagebuf_bitmap_scale=0;
3261 #define IMAGEBUF_SCALE (imagebuf_bitmap_scale > 0 ? imagebuf_bitmap_scale : 1.0 / -imagebuf_bitmap_scale)
3262 int32_t imagesize=0;
3263 int32_t tilecount=0;
3264 int32_t imagetype=0;
3265 int32_t imagex,imagey,selx,sely;
3266 int32_t bp=4,grabmode=16,romofs=0,romtilemode=0, romtilecols=8;
3267 bool nesmode=false;
3268 int32_t grabmask=0;
3269 recolorState recolor=rcNone;
3270 PALETTE imagepal;
3271
3272 /* bestfit_color:
3273 * Searches a palette for the color closest to the requested R, G, B value.
3274 */
3275 int32_t bestfit_cset_color(int32_t cs, int32_t r, int32_t g, int32_t b)
3276 {
3277 int32_t bestMatch = 0; // Color with the lowest total difference so far
3278 float bestTotalDiff = 100000; // Total difference between requested color and bestMatch
3279 float bestHighDiff = 100000; // Greatest difference of R, G, B between requested color and bestMatch
3280
3281 for(int32_t i = 0; i < CSET_SIZE; i++)
3282 {
3283 byte *rgbByte;
3284
3285 // This seems to be right...
3286 if(cs==2 || cs==3 || cs==4)
3287 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + i) * 3;
3288 else if(cs==9)
3289 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + i) * 3;
3290 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3291 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + i) * 3;
3292 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3293 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + i) * 3;
3294 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3295 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + i) * 3;
3296 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3297 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + i) * 3;
3298 else
3299 rgbByte = colordata + (CSET(cs)+i)*3;
3300
3301 int32_t dr=r-*rgbByte;
3302 int32_t dg=g-*(rgbByte+1);
3303 int32_t db=b-*(rgbByte+2);
3304
3305 // Track both the total color difference and the single greatest
3306 // difference of R, G, B. The idea is that it's better to have
3307 // two or three small differences than one big one.
3308 // The differences are multiplied by different numbers to account
3309 // for the differences in perceived brightness of the three colors.
3310 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3311 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3312
3313 // Perfect match? Just stop here.
3314 if(totalDiff==0)
3315 return i;
3316
3317 if(totalDiff < bestTotalDiff || // Best match so far?
3318 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3319 {
3320 bestMatch=i;
3321 bestTotalDiff=totalDiff;
3322 bestHighDiff=highDiff;
3323 }
3324 }
3325
3326 return bestMatch;
3327 }
3328
3329 // Same as the above, but draws from all colors in CSets 0-11.
3330 int32_t bestfit_cset_color_8bit(int32_t r, int32_t g, int32_t b)
3331 {
3332 int32_t bestMatch = 0;
3333 float bestTotalDiff = 100000;
3334 float bestHighDiff = 100000;
3335
3336 for(int32_t i = 0; i < 192; i++) // 192 colors in CSets 0-11
3337 {
3338 byte *rgbByte;
3339
3340 int32_t cs=i>>4;
3341 if(cs==2 || cs==3 || cs==4)
3342 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + (i%16)) * 3;
3343 else if(cs==9)
3344 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + (i%16)) * 3;
3345 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3346 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + (i%16)) * 3;
3347 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3348 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + (i%16)) * 3;
3349 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3350 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + (i%16)) * 3;
3351 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3352 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + (i%16)) * 3;
3353 else
3354 rgbByte = colordata + i * 3;
3355
3356 int32_t dr=r-*rgbByte;
3357 int32_t dg=g-*(rgbByte+1);
3358 int32_t db=b-*(rgbByte+2);
3359
3360 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3361 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3362
3363 if(totalDiff==0) // Perfect match?
3364 return i;
3365
3366 if(totalDiff < bestTotalDiff || // Best match so far?
3367 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3368 {
3369 bestMatch=i;
3370 bestTotalDiff=totalDiff;
3371 bestHighDiff=highDiff;
3372 }
3373 }
3374
3375 return bestMatch;
3376 }
3377
3378 byte cset_reduce_table[PAL_SIZE];
3379
3380 void calc_cset_reduce_table(PALETTE pal, int32_t cs)
3381 {
3382 for(int32_t i=0; i<PAL_SIZE; i++)
3383 {
3384 cset_reduce_table[i]=(bestfit_cset_color(cs, pal[i].r, pal[i].g, pal[i].b)&0x0F);
3385 }
3386 }
3387
3388 void calc_cset_reduce_table_8bit(PALETTE pal)
3389 {
3390 for(int32_t i=0; i<PAL_SIZE; i++)
3391 {
3392 cset_reduce_table[i]=bestfit_cset_color_8bit(pal[i].r, pal[i].g, pal[i].b);
3393 }
3394 }
3395
3396 void puttileROM(BITMAP *dest,int32_t x,int32_t y,byte *src,int32_t cs)
3397 {
3398 //storage space for the grabbed image
3399 byte buf[64];
3400 memset(buf,0,64);
3401 byte *oldsrc=src;
3402
3403 //for 8 lines in the source image...
3404 for(int32_t line=0; line<(nesmode?4:8); line++)
3405 {
3406 //bx is the pixel at the start of a line in the storage buffer
3407 int32_t bx=line<<(nesmode?4:3);
3408 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3409 byte b=src[(bp&1)?line:line<<1];
3410
3411 //fill the storage buffer with data from the source image
3412 for(int32_t i=7; i>=0; --i)
3413 {
3414 buf[bx+i] = (b&1)+(cs<<4);
3415 b>>=1;
3416 }
3417 }
3418
3419 ++src;
3420
3421 for(int32_t p=1; p<bp; p++)
3422 {
3423 for(int32_t line=0; line<(nesmode?4:8); line++)
3424 {
3425 int32_t bx=line<<(nesmode?4:3);
3426 byte b=src[(bp&1)?line:line<<1];
3427
3428 for(int32_t i=7; i>=0; --i)
3429 {
3430 if(nesmode)
3431 {
3432 buf[bx+8+i] = (b&1)+(cs<<4);
3433 }
3434 else
3435 {
3436 buf[bx+i] |= (b&1)<<p;
3437 }
3438
3439 b>>=1;
3440 }
3441 }
3442
3443 if(p&1)
3444 {
3445 src+=15;
3446 }
3447 else
3448 {
3449 ++src;
3450 }
3451 }
3452
3453
3454 if(nesmode)
3455 {
3456 src=oldsrc;
3457
3458 for(int32_t counter=0; counter<2; ++counter, ++src)
3459 {
3460 //for 8 lines in the source image...
3461 for(int32_t line=0; line<4; line++)
3462 {
3463 //bx is the pixel at the start of a line in the storage buffer
3464 int32_t bx=line<<4;
3465 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3466 byte b=src[(line+4)<<1];
3467
3468 //fill the storage buffer with data from the source image
3469 for(int32_t i=7; i>=0; --i)
3470 {
3471 // buf[bx+i] = (b&1)+(cs<<4);
3472 buf[bx+(counter<<3)+i] |= (b&1)<<1;
3473 b>>=1;
3474 }
3475 }
3476 }
3477 }
3478
3479 int32_t c=0;
3480
3481 switch(romtilemode)
3482 {
3483 case 0:
3484 case 1:
3485 case 2:
3486 for(int32_t j=0; j<8; j++)
3487 {
3488 for(int32_t i=0; i<8; i++)
3489 {
3490 putpixel(dest,x+i,y+j,buf[c++]);
3491 }
3492 }
3493
3494 break;
3495
3496 case 3:
3497 for(int32_t j=0; j<4; j++)
3498 {
3499 for(int32_t i=0; i<16; i++)
3500 {
3501 putpixel(dest,x+i,y+j,buf[c++]);
3502 }
3503 }
3504
3505 break;
3506 }
3507 }
3508
3509 const char *file_type[ftMAX]=
3510 {
3511 "None", "BIN", "BMP", "TIL", "ZGP", "QSU", "ZQT", "QST"
3512 };
3513
3514 void draw_grab_window()
3515 {
3516 int w = 640;
3517 int h = 480;
3518 int window_xofs=0;//(zq_screen_w-w-12)>>1;
3519 int window_yofs=0;//(zq_screen_h-h-25-6)>>1;
3520 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
3521 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+2+2-(79*2), FR_DEEP);
3522
3523 FONT *oldfont = font;
3524 font = get_zc_font(font_lfont);
3525 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Grab Tile(s)", true);
3526 font=oldfont;
3527 }
3528
3529 void draw_grab_scr(int32_t tile,int32_t cs,byte *newtile,int32_t black,int32_t white, int32_t width, int32_t height, byte *newformat)
3530 {
3531 width=width;
3532 height=height;
3533 white=white; // happy birthday compiler
3534
3535 int32_t yofs=0;
3536 //clear_to_color(screen2,bg);
3537 rectfill(screen2, 0, 0, 319, 159, black);
3538 rectfill(screen2,0,162,319,239,jwin_pal[jcBOX]);
3539 hline(screen2, 0, 160, 319, jwin_pal[jcMEDLT]);
3540 hline(screen2, 0, 161, 319, jwin_pal[jcLIGHT]);
3541 yofs=3;
3542
3543 // text_mode(-1);
3544 int32_t tileromcolumns=20;
3545
3546 switch(imagetype)
3547 {
3548 case ftBMP:
3549 if(recolor==rcNone)
3550 {
3551 blit((BITMAP*)imagebuf,screen2,imagex<<4,imagey<<4,0,0,320,160);
3552 }
3553 else
3554 {
3555 int32_t maxy=zc_min(160,((BITMAP*)imagebuf)->h);
3556 int32_t maxx=zc_min(320,((BITMAP*)imagebuf)->w);
3557
3558 for(int32_t y=0; y<maxy; y++)
3559 {
3560 if((imagey<<4)+y>=((BITMAP*)imagebuf)->h)
3561 {
3562 break;
3563 }
3564
3565 for(int32_t x=0; x<maxx; x++)
3566 {
3567 if((imagex<<4)+x>=((BITMAP*)imagebuf)->w)
3568 {
3569 break;
3570 }
3571
3572 if(recolor==rc8Bit)
3573 screen2->line[y][x]=cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]];
3574 else
3575 screen2->line[y][x]=(cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]])+(cs<<4);
3576 }
3577 }
3578 }
3579
3580 break;
3581
3582 case ftZGP:
3583 case ftQST:
3584 case ftZQT:
3585 case ftQSU:
3586 case ftTIL:
3587 {
3588 tiledata *hold = newtilebuf;
3589 newtilebuf = grabtilebuf;
3590 //fixme
3591 imagey = vbound(imagey, 0, MAXTILEROWS); //fixed -Z This can no longer crash if you scroll past the end of the tile pages. 6th June, 2020
3592 int32_t t=imagey*TILES_PER_ROW;
3593
3594 for(int32_t i=0; i<200; i++) // 10 rows, down to y=160
3595 {
3596 if(t <= tilecount)
3597 {
3598 puttile16(screen2,t,(i%TILES_PER_ROW)<<4,(i/TILES_PER_ROW)<<4,cs,0);
3599 }
3600
3601 ++t;
3602 }
3603
3604 newtilebuf = hold;
3605 //fixme
3606 }
3607 break;
3608
3609 case ftBIN:
3610 {
3611 int32_t ofs = (tileromcolumns*imagex + imagey) * 128*bp + romofs;
3612 byte *buf = (byte*)imagebuf;
3613
3614 switch(romtilemode)
3615 {
3616 case 0:
3617 for(int32_t y=0; y<160; y+=8)
3618 {
3619 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3620 {
3621 puttileROM(screen2,x,y,buf+ofs,cs);
3622 ofs+=8*bp;
3623 }
3624 }
3625
3626 for(int32_t y=0; y<160; y+=8)
3627 {
3628 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3629 {
3630 puttileROM(screen2,x+128,y,buf+ofs,cs);
3631 ofs+=8*bp;
3632 }
3633 }
3634
3635 break;
3636
3637 case 1:
3638 for(int32_t y=0; y<160; y+=16)
3639 {
3640 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3641 {
3642 puttileROM(screen2,x,y,buf+ofs,cs);
3643 ofs+=8*bp;
3644 puttileROM(screen2,x,y+8,buf+ofs,cs);
3645 ofs+=8*bp;
3646 }
3647 }
3648
3649 for(int32_t y=0; y<160; y+=16)
3650 {
3651 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3652 {
3653 puttileROM(screen2,x+128,y,buf+ofs,cs);
3654 ofs+=8*bp;
3655 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3656 ofs+=8*bp;
3657 }
3658 }
3659
3660 break;
3661
3662 case 2:
3663 for(int32_t y=0; y<160; y+=16)
3664 {
3665 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3666 {
3667 puttileROM(screen2,x,y,buf+ofs,cs);
3668 ofs+=8*bp;
3669 puttileROM(screen2,x+8,y,buf+ofs,cs);
3670 ofs+=8*bp;
3671 puttileROM(screen2,x,y+8,buf+ofs,cs);
3672 ofs+=8*bp;
3673 puttileROM(screen2,x+8,y+8,buf+ofs,cs);
3674 ofs+=8*bp;
3675 }
3676 }
3677
3678 for(int32_t y=0; y<160; y+=16)
3679 {
3680 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3681 {
3682 puttileROM(screen2,x+128,y,buf+ofs,cs);
3683 ofs+=8*bp;
3684 puttileROM(screen2,x+136,y,buf+ofs,cs);
3685 ofs+=8*bp;
3686 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3687 ofs+=8*bp;
3688 puttileROM(screen2,x+136,y+8,buf+ofs,cs);
3689 ofs+=8*bp;
3690 }
3691 }
3692
3693 break;
3694
3695 case 3:
3696 for(int32_t y=0; y<160; y+=16)
3697 {
3698 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3699 {
3700 puttileROM(screen2,x,y,buf+ofs,cs);
3701 ofs+=8*bp;
3702 puttileROM(screen2,x,y+4,buf+ofs,cs);
3703 ofs+=8*bp;
3704 puttileROM(screen2,x,y+8,buf+ofs,cs);
3705 ofs+=8*bp;
3706 puttileROM(screen2,x,y+12,buf+ofs,cs);
3707 ofs+=8*bp;
3708 }
3709 }
3710
3711 for(int32_t y=0; y<160; y+=16)
3712 {
3713 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3714 {
3715 puttileROM(screen2,x+128,y,buf+ofs,cs);
3716 ofs+=8*bp;
3717 puttileROM(screen2,x+128,y+4,buf+ofs,cs);
3718 ofs+=8*bp;
3719 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3720 ofs+=8*bp;
3721 puttileROM(screen2,x+128,y+12,buf+ofs,cs);
3722 ofs+=8*bp;
3723 }
3724 }
3725
3726 break;
3727 }
3728 }
3729 break;
3730 }
3731
3732 tiledata hold;
3733 bool holdblank = blank_tile_table[0];
3734
3735 if(is_valid_format(newtilebuf[0].format))
3736 {
3737 hold.format = newtilebuf[0].format;
3738 hold.data = (byte *)malloc(tilesize(hold.format));
3739 memcpy(hold.data, newtilebuf[0].data, tilesize(hold.format));
3740 }
3741 else
3742 {
3743 hold.format=tfInvalid;
3744 hold.data=NULL;
3745 }
3746
3747 newtilebuf[0].format=newformat[0];
3748 blank_tile_table[0] = false;
3749
3750 if(newtilebuf[0].data!=NULL)
3751 {
3752 free(newtilebuf[0].data);
3753 }
3754
3755 if(is_valid_format(newtilebuf[0].format))
3756 {
3757 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3758
3759 for(int32_t i=0; i<tilesize(newtilebuf[0].format); i++)
3760 {
3761 newtilebuf[0].data[i]=newtile[i];
3762 }
3763 }
3764 else
3765 {
3766 newtilebuf[0].data=NULL;
3767 }
3768
3769 puttile16(screen2,0,208,168+yofs,cs,0);
3770 overtile16(screen2,0,232,168+yofs,cs,0);
3771 newtilebuf[0].format=hold.format;
3772 blank_tile_table[0] = holdblank;
3773
3774 if(newtilebuf[0].data!=NULL)
3775 {
3776 free(newtilebuf[0].data);
3777 }
3778
3779 if(is_valid_format(newtilebuf[0].format))
3780 {
3781 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3782
3783 for(int32_t i=0; i<256; i++)
3784 {
3785 newtilebuf[0].data[i]=hold.data[i];
3786 }
3787 }
3788 else
3789 {
3790 newtilebuf[0].data=NULL;
3791 }
3792
3793 if(hold.data!=NULL)
3794 {
3795 free(hold.data);
3796 }
3797
3798 puttile16(screen2,tile,208,192+yofs,cs,0);
3799 overtile16(screen2,tile,232,192+yofs,cs,0);
3800
3801 rectfill(screen2,184,168+yofs,191,175+yofs,grabmask&1?vc(12):vc(7));
3802 rectfill(screen2,192,168+yofs,199,175+yofs,grabmask&2?vc(12):vc(7));
3803 rectfill(screen2,184,176+yofs,191,183+yofs,grabmask&4?vc(12):vc(7));
3804 rectfill(screen2,192,176+yofs,199,183+yofs,grabmask&8?vc(12):vc(7));
3805
3806 // rect(screen2,183,167,200,184,dvc(7*2));
3807 // rect(screen2,207,167,224,184,dvc(7*2));
3808 // rect(screen2,231,167,248,184,dvc(7*2));
3809 // rect(screen2,207,191,224,208,dvc(7*2));
3810 // rect(screen2,231,191,248,208,dvc(7*2));
3811
3812 /*
3813 rect(screen2,183,167,200,184,vc(14));
3814 rect(screen2,207,167,224,184,vc(14));
3815 rect(screen2,231,167,248,184,vc(14));
3816 rect(screen2,207,191,224,208,vc(14));
3817 rect(screen2,231,191,248,208,vc(14));
3818 */
3819 jwin_draw_frame(screen2,182,166+yofs,20,20,FR_DEEP);
3820 jwin_draw_frame(screen2,206,166+yofs,20,20,FR_DEEP);
3821 jwin_draw_frame(screen2,230,166+yofs,20,20,FR_DEEP);
3822 jwin_draw_frame(screen2,206,190+yofs,20,20,FR_DEEP);
3823 jwin_draw_frame(screen2,230,190+yofs,20,20,FR_DEEP);
3824 int32_t screen_xofs=6;
3825 int32_t screen_yofs=25;
3826 int winh = 511;
3827 int32_t mul = 2;
3828
3829 yofs=16;
3830
3831 custom_vsync();
3832
3833 stretch_blit(screen2,screen,0,0,320,240,screen_xofs,screen_yofs,640,480);
3834
3835 // Suspend the current font while draw_text_button does its work
3836 FONT* oldfont = font;
3837
3838 font = get_zc_font(font_lfont_l);
3839
3840 int txt_x = 8*mul;
3841 int rbtn_x = 255*mul;
3842 int max_fpath_wid = rbtn_x-2-txt_x;
3843 int max_fpath_wid2 = max_fpath_wid-text_length(font,"... ");
3844 // Interface
3845 switch(imagetype)
3846 {
3847 case 0:
3848 textprintf_ex(screen,font,txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s",imgstr[imagetype]);
3849 break;
3850
3851 case ftBMP:
3852 {
3853 std::string text = fmt::format("{} {}x{}, {:.2g}x zoom with , and .", imgstr[imagetype], original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, IMAGEBUF_SCALE);
3854 int text_x = txt_x;
3855 int text_y = (216 + yofs) * mul;
3856 // TODO: can almost use this, but drawing is offset. prob cuz drawing to a different bitmap than the normal screen bitmap? idk
3857 // int text_w = text_length(font, text.c_str());
3858 // int text_h = text_height(font);
3859 // static int grab_scale_tooltip_id = ttip_register_id();
3860 // ttip_install(grab_scale_tooltip_id, "zoom with , and .", text_x, text_y, text_w, text_h, text_x, text_y - 40);
3861 textprintf_ex(screen, font, text_x, text_y, jwin_pal[jcTEXTFG], jwin_pal[jcBOX], "%s", text.c_str());
3862
3863 draw_text_button(screen,117*mul,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Recolor",vc(1),vc(14),0,true);
3864 break;
3865 }
3866
3867 case ftZGP:
3868 case ftQST:
3869 case ftZQT:
3870 case ftQSU:
3871 case ftTIL:
3872 case ftBIN:
3873 textprintf_ex(screen,get_zc_font(font_lfont_l),txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s %d KB",imgstr[imagetype],imagesize>>10);
3874 break;
3875 }
3876
3877 textprintf_ex(screen,font,txt_x,(168+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"sel: %d %d",selx,sely);
3878 textprintf_ex(screen,font,txt_x,(176+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"pos: %d %d",imagex,imagey);
3879
3880 if(bp==8)
3881 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"8-bit");
3882 else
3883 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"cset: %d",cs);
3884 textprintf_ex(screen,font,txt_x,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"step: %d",grabmode);
3885
3886 if(imagetype==ftBIN)
3887 {
3888 textprintf_ex(screen,font,104*mul,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"bp: %d%s",bp,nesmode?" (NES)":"");
3889 textprintf_ex(screen,font,104*mul,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"ofs: %Xh",romofs);
3890 textprintf_ex(screen,font,104*mul,(208+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"m: %d",romtilemode);
3891 }
3892
3893 int fpath_y = (224+yofs)*mul;
3894 if(text_length(font,imagepath) <= max_fpath_wid)
3895 textout_ex(screen,font,imagepath,txt_x,fpath_y,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3896 else
3897 {
3898 char buf[2052] = {0};
3899 strncpy(buf,imagepath,2048);
3900 int len = strlen(buf);
3901 char *ptr = buf;
3902 char *endptr = buf+len;
3903 char *it = endptr;
3904 int tmpy = fpath_y;
3905 int tmph = text_height(font)+1;
3906 while(true)
3907 {
3908 if(tmpy+tmph > (winh-2))
3909 break; //Out of space!
3910 char c = *it;
3911 bool end = !c;
3912 *it = 0;
3913 int newlen = text_length(font,ptr);
3914 if(newlen <= (end ? max_fpath_wid : max_fpath_wid2))
3915 {
3916 if(end) //No stored character, string ended
3917 {
3918 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3919 break;
3920 }
3921 char t[5];
3922 t[0] = c;
3923 for(int q = 1; q < 5; ++q)
3924 t[q] = it[q];
3925 strcpy(it,"...");
3926 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3927 for(int q = 0; q < 5; ++q)
3928 it[q] = t[q];
3929 tmpy += tmph;
3930 ptr = it;
3931 it = endptr;
3932 }
3933 else
3934 {
3935 *it = c;
3936 --it;
3937 }
3938 }
3939 }
3940 draw_text_button(screen,rbtn_x,(168+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"OK",vc(1),vc(14),0,true);
3941 draw_text_button(screen,rbtn_x,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Cancel",vc(1),vc(14),0,true);
3942 draw_text_button(screen,rbtn_x,(216+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"File",vc(1),vc(14),0,true);
3943 draw_text_button(screen,117*mul,(166+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Leech",vc(1),vc(14),0,true);
3944
3945 //int32_t rectw = 16*mul;
3946 //rect(screen,selx+screen_xofs,sely+screen_yofs,selx+screen_xofs+((width-1)*rectw)+rectw-1,sely+screen_yofs+((height-1)*rectw)+rectw-1,white);
3947 SCRFIX();
3948 font = oldfont;
3949 }
3950
3951 RGB_MAP rgb_table;
3952 COLOR_MAP imagepal_table;
3953
3954
3955 extern void return_RAMpal_color(AL_CONST PALETTE pal, int32_t x, int32_t y, RGB *rgb)
3956 {
3957 //these are here to bypass compiler warnings about unused arguments
3958 x=x;
3959
3960 rgb->r = pal[y].r;
3961 rgb->g = pal[y].g;
3962 rgb->b = pal[y].b;
3963 }
3964
3965
3966 void load_imagebuf()
3967 {
3968 PACKFILE *f;
3969 //cache QRS
3970 //byte cached_rules[QUESTRULES_NEW_SIZE] = { 0 };
3971 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
3972 // {
3973 // cached_rules[q] = quest_rules[q];
3974 // }
3975 bool compressed=false;
3976 bool encrypted=false;
3977 tiledata *hold=newtilebuf;
3978 zquestheader tempheader{};
3979
3980 if(imagebuf)
3981 {
3982 switch(imagetype)
3983 {
3984 case ftBMP:
3985 if (original_imagebuf_bitmap != imagebuf)
3986 destroy_bitmap((BITMAP*)imagebuf);
3987 destroy_bitmap(original_imagebuf_bitmap);
3988 break;
3989
3990 case ftZGP:
3991 case ftQST:
3992 case ftZQT:
3993 case ftQSU:
3994 case ftTIL:
3995 clear_tiles(grabtilebuf);
3996 break;
3997
3998 case ftBIN:
3999 free(imagebuf);
4000 break;
4001 }
4002
4003 imagebuf=NULL;
4004 original_imagebuf_bitmap=NULL;
4005 }
4006
4007 selx=sely=romofs=0;
4008 bp=4;
4009 imagetype=filetype(imagepath);
4010
4011 dword section_id;
4012 word section_version;
4013
4014 switch(imagetype)
4015 {
4016 case ftBMP:
4017 packfile_password("");
4018 memset(imagepal, 0, sizeof(PALETTE));
4019 original_imagebuf_bitmap = load_bitmap(imagepath,imagepal);
4020 imagesize = file_size_ex_password(imagepath,"");
4021 tilecount=0;
4022 create_rgb_table(&rgb_table, imagepal, NULL);
4023 rgb_map = &rgb_table;
4024 create_color_table(&imagepal_table, RAMpal, return_RAMpal_color, NULL);
4025
4026 if(!original_imagebuf_bitmap)
4027 {
4028 imagetype=0;
4029 }
4030 else
4031 {
4032 imagebuf = original_imagebuf_bitmap;
4033 imagebuf_bitmap_scale = 1;
4034 }
4035
4036 break;
4037
4038 case ftBIN:
4039 packfile_password("");
4040 imagesize = file_size_ex_password(imagepath, "");
4041 tilecount=0;
4042
4043 if(imagesize)
4044 {
4045 imagebuf = malloc(imagesize);
4046
4047 if(!readfile(imagepath,imagebuf,imagesize))
4048 {
4049 free(imagebuf);
4050 imagesize=0;
4051 imagetype=0;
4052 }
4053 }
4054
4055 break;
4056
4057 case ftTIL:
4058 packfile_password("");
4059 imagesize = file_size_ex_password(imagepath,"");
4060 f = pack_fopen_password(imagepath,F_READ,"");
4061
4062 if(!f)
4063 {
4064 goto error;
4065 }
4066
4067 if(!p_mgetl(&section_id,f))
4068 {
4069 goto error;
4070 }
4071
4072 if(section_id==ID_TILES)
4073 {
4074 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)==0)
4075 {
4076 goto error;
4077 }
4078 }
4079
4080 error:
4081 pack_fclose(f);
4082 tilecount=count_tiles(grabtilebuf);
4083 break;
4084
4085 case ftZGP:
4086 packfile_password("");
4087 imagesize = file_size_ex_password(imagepath, "");
4088 f=pack_fopen_password(imagepath,F_READ,"");
4089
4090 if(!f)
4091 {
4092 goto error2;
4093 }
4094
4095 if(!p_mgetl(&section_id,f))
4096 {
4097 goto error2;
4098 }
4099
4100 if(section_id!=ID_GRAPHICSPACK)
4101 {
4102 goto error2;
4103 }
4104
4105 //section version info
4106 if(!p_igetw(&section_version,f))
4107 {
4108 goto error2;
4109 }
4110
4111 if(!read_deprecated_section_cversion(f))
4112 {
4113 goto error2;
4114 }
4115
4116 //tiles
4117 if(!p_mgetl(&section_id,f))
4118 {
4119 goto error2;
4120 }
4121
4122 if(section_id==ID_TILES)
4123 {
4124 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)!=0)
4125 {
4126 goto error2;
4127 }
4128 }
4129
4130 error2:
4131 pack_fclose(f);
4132 tilecount=count_tiles(grabtilebuf);
4133 break;
4134
4135 case ftQST:
4136 encrypted=true;
4137 case ftZQT:
4138 compressed=true;
4139 case ftQSU:
4140 packfile_password("");
4141 imagesize = file_size_ex_password(imagepath, encrypted ? datapwd : "");
4142 newtilebuf=grabtilebuf;
4143 byte skip_flags[4];
4144
4145 for(int32_t i=0; i<skip_max; ++i)
4146 {
4147 set_bit(skip_flags,i,1);
4148 }
4149
4150 set_bit(skip_flags,skip_tiles,0);
4151 set_bit(skip_flags,skip_header,0);
4152 int ret = loadquest(imagepath,&tempheader,&QMisc,customtunes,true,skip_flags);
4153 if (ret)
4154 {
4155 imagetype=0;
4156 imagesize=0;
4157 clear_tiles(grabtilebuf);
4158 chop_path(imagepath);
4159 }
4160
4161 if (!ret && encrypted && compressed)
4162 {
4163 if(quest_access(imagepath, &tempheader) != 1)
4164 {
4165 imagetype=0;
4166 imagesize=0;
4167 clear_tiles(grabtilebuf);
4168 chop_path(imagepath);
4169 }
4170 }
4171
4172 //setPackfilePassword(NULL);
4173 newtilebuf=hold;
4174 tilecount=count_tiles(grabtilebuf);
4175 break;
4176 }
4177
4178 rgb_map = &zq_rgb_table;
4179 //restore cashed QRs / rules
4180
4181 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
4182 // {
4183 // quest_rules[q] = cached_rules[q];
4184 // }
4185 }
4186
4187 static char bitstrbuf[32];
4188 bool leeching_from_tiles=false;
4189
4190 const char *bitlist(int32_t index, int32_t *list_size)
4191 {
4192 int32_t imported=2;
4193
4194 if(index>=0)
4195 {
4196 bound(index,0,leeching_from_tiles?2:1);
4197
4198 if(index==imported)
4199 {
4200 sprintf(bitstrbuf,"Imported");
4201 }
4202 else
4203 {
4204 sprintf(bitstrbuf,"%d",4<<index);
4205 }
4206
4207 return bitstrbuf;
4208 }
4209
4210 *list_size=leeching_from_tiles?3:2;
4211 return NULL;
4212 }
4213
4214 12 static ListData bit_list(bitlist, &font);
4215
4216 static DIALOG leech_dlg[] =
4217 {
4218 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
4219 12 { jwin_win_proc, 8, 20-4, 303+1, 216-42+1, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Leech Options", NULL, NULL },
4220 12 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
4221 // 2
4222 12 { jwin_button_proc, 180, 210-42-4, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
4223 12 { jwin_button_proc, 80, 210-42-4, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
4224 12 { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL },
4225 // 5
4226 12 { jwin_text_proc, 14, 49-4, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Update Status Every: ", NULL, NULL },
4227 12 { jwin_edit_proc, 114, 45-4, 36, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL },
4228 12 { jwin_radio_proc, 155, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Tiles", NULL, NULL },
4229 12 { jwin_radio_proc, 200, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Seconds", NULL, NULL },
4230 //9
4231 12 { jwin_frame_proc, 14, 63-2, 176+70, 50+30, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL },
4232 12 { jwin_text_proc, 14+8, 60-2, 80, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) " Duplicates ", NULL, NULL },
4233
4234 12 { jwin_check_proc, 20, 70, 168, 8+1, vc(15), vc(1), 0, 0, 1, 0, (void *) "Only check new tiles", NULL, NULL },
4235 12 { jwin_text_proc, 20, 90, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Normal:", NULL, NULL },
4236 12 { jwin_text_proc, 20, 100, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal Flip:", NULL, NULL },
4237 12 { jwin_text_proc, 20, 110, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Vertical Flip:", NULL, NULL },
4238 12 { jwin_text_proc, 20, 120, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal/Vertical Flip:", NULL, NULL },
4239 //16
4240 12 { jwin_radio_proc, 144, 90, 64+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4241 12 { jwin_radio_proc, 184, 90, 56+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4242 12 { jwin_radio_proc, 224, 90, 72+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4243
4244 12 { jwin_radio_proc, 144, 100, 64+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4245 12 { jwin_radio_proc, 184, 100, 56+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4246 12 { jwin_radio_proc, 224, 100, 72+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4247
4248 12 { jwin_radio_proc, 144, 110, 64+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4249 12 { jwin_radio_proc, 184, 110, 56+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4250 12 { jwin_radio_proc, 224, 110, 72+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4251
4252 12 { jwin_radio_proc, 144, 120, 64+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4253 12 { jwin_radio_proc, 184, 120, 56+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4254 12 { jwin_radio_proc, 224, 120, 72+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4255
4256 12 { jwin_ctext_proc, 144+4, 80, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Ignore", NULL, NULL },
4257 12 { jwin_ctext_proc, 184+4, 80, 56+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Check", NULL, NULL },
4258 12 { jwin_ctext_proc, 224+4, 80, 72+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Discard", NULL, NULL },
4259 12 { jwin_droplist_proc, 76, 145, 80, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &bit_list, NULL, NULL },
4260 12 { jwin_text_proc, 14, 149, 60, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Color Depth: ", NULL, NULL },
4261 12 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
4262 };
4263
4264 bool leech_tiles(tiledata *dest,int32_t start,int32_t cs)
4265 {
4266 bool shift=true; // fix this!
4267 int32_t cst=0;
4268 int32_t currtile=start;
4269 int32_t height=0, width=0;
4270 byte *testtile = new byte[tilesize(tf32Bit)];
4271 byte imported_format=0;
4272 char updatestring[6];
4273 bool canadd;
4274 bool temp_canadd;
4275 bool duplicate;
4276 int32_t total_duplicates_found=0, total_duplicates_discarded=0;
4277 int32_t duplicates_found[4]= //, duplicates_discarded[4]={0,0,0,0};
4278 {
4279 0,0,0,0
4280 };
4281 BITMAP *status;
4282 status = create_bitmap_ex(8,240,140);
4283 clear_bitmap(status);
4284 sprintf(updatestring, "%d", LeechUpdate);
4285 leech_dlg[0].dp2=get_zc_font(font_lfont);
4286 leech_dlg[6].dp=updatestring;
4287
4288 leech_dlg[10].flags=(OnlyCheckNewTilesForDuplicates!=0) ? D_SELECTED : 0;
4289
4290 for(int32_t i=0; i<2; i++)
4291 {
4292 leech_dlg[i+7].flags=0;
4293 }
4294
4295 leech_dlg[7+((LeechUpdateTiles==0) ? 1 : 0)].flags=D_SELECTED;
4296
4297 for(int32_t i=0; i<12; i++)
4298 {
4299 leech_dlg[i+16].flags=0;
4300 }
4301
4302 for(int32_t i=0; i<4; i++)
4303 {
4304 leech_dlg[(DuplicateAction[i])+16+(i*3)].flags=D_SELECTED;
4305 }
4306
4307 leech_dlg[31].d1=0;
4308
4309 large_dialog(leech_dlg);
4310
4311 int32_t ret = do_zqdialog(leech_dlg,3);
4312
4313 if(ret==2)
4314 {
4315 delete[] testtile;
4316 return false;
4317 }
4318
4319 int32_t cdepth=leech_dlg[31].d1+1;
4320 int32_t newformat=0;
4321 auto lu = atoi(updatestring);
4322 auto lut = (leech_dlg[7].flags&D_SELECTED)?1:0;
4323 if(LeechUpdate!=lu)
4324 {
4325 LeechUpdate=lu;
4326 zc_set_config("zquest","leech_update",LeechUpdate);
4327 }
4328 if(LeechUpdateTiles!=lut)
4329 {
4330 LeechUpdateTiles=lut;
4331 zc_set_config("zquest","leech_update_tiles",LeechUpdateTiles);
4332 }
4333
4334 int32_t old_dupe[4];
4335 for(int32_t j=0; j<4; j++)
4336 {
4337 old_dupe[j] = DuplicateAction[j];
4338 for(int32_t i=0; i<3; i++)
4339 {
4340 if(leech_dlg[i+16+(j*3)].flags&D_SELECTED)
4341 {
4342 DuplicateAction[j]=i;
4343 }
4344 }
4345 }
4346 if(old_dupe[0] != DuplicateAction[0])
4347 zc_set_config("zquest","normal_duplicate_action",DuplicateAction[0]);
4348 if(old_dupe[1] != DuplicateAction[1])
4349 zc_set_config("zquest","horizontal_duplicate_action",DuplicateAction[1]);
4350 if(old_dupe[2] != DuplicateAction[2])
4351 zc_set_config("zquest","vertical_duplicate_action",DuplicateAction[2]);
4352 if(old_dupe[3] != DuplicateAction[3])
4353 zc_set_config("zquest","both_duplicate_action",DuplicateAction[3]);
4354
4355 auto ocntfd = leech_dlg[10].flags&D_SELECTED?1:0;
4356 if(OnlyCheckNewTilesForDuplicates!=ocntfd)
4357 {
4358 OnlyCheckNewTilesForDuplicates=ocntfd;
4359 zc_set_config("zquest","only_check_new_tiles_for_duplicates",ocntfd);
4360 }
4361
4362 leeching_from_tiles=false;
4363
4364 switch(imagetype)
4365 {
4366 case ftBIN:
4367 width=imagesize/128;
4368 height=1;
4369 break;
4370
4371 case ftZGP:
4372 case ftQST:
4373 case ftZQT:
4374 case ftQSU:
4375 case ftTIL:
4376 leeching_from_tiles=true;
4377 width=count_tiles(grabtilebuf);
4378 height=1;
4379 break;
4380
4381 case ftBMP:
4382 width=((((BITMAP*)imagebuf)->w)+15)/16;
4383 height=((((BITMAP*)imagebuf)->h)+15)/16;
4384 break;
4385 }
4386
4387 if(currtile+(width*height)>NEWMAXTILES)
4388 {
4389 if(jwin_alert("Confirm Truncation","Too many tiles.","Truncation may occur.",NULL,"&OK","&Cancel",'o','c',get_zc_font(font_lfont))==2)
4390 {
4391 delete[] testtile;
4392 return false;
4393 }
4394 }
4395
4396 go_tiles();
4397 saved=false;
4398
4399 for(int32_t ty=0; ty<height; ty++) //for every row
4400 {
4401 for(int32_t tx=0; tx<width; tx++) //for every column (tile)
4402 {
4403 if((((ty*width)+tx)%zc_max(LeechUpdate, 1))==0) //update status
4404 {
4405 FONT *oldfont = font;
4406 static BITMAP *tbar = create_bitmap_ex(8,240-6, 18);
4407 static bool created_tbar=false;
4408 jwin_draw_win(status, 0, 0, 240, 140, FR_WIN);
4409
4410 if(created_tbar)
4411 {
4412 blit(tbar, status, 0, 0, 3, 3, 240-6, 18);
4413 }
4414 else
4415 {
4416 font = get_zc_font(font_lfont);
4417 jwin_draw_titlebar(tbar, 0, 0, 240-6, 18, "Leech Status", false);
4418 font = oldfont;
4419 created_tbar=true;
4420 blit(tbar, status, 0, 0, 3, 3, 320-6, 18);
4421 }
4422
4423 textprintf_centre_ex(status,font,120,24,jwin_pal[jcTEXTFG],-1,"Checking %d of %d",((ty*width)+tx), (width*height));
4424 textprintf_centre_ex(status,font,120,34,jwin_pal[jcTEXTFG],-1,"%d tiles imported",currtile-start);
4425 jwin_draw_frame(status, 40, 49, 160, 70, FR_ETCHED);
4426 textprintf_centre_ex(status,font,120,46,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]," Duplicates ");
4427 textprintf_centre_ex(status,font,120,56,jwin_pal[jcTEXTFG],-1,"%d/%d found/discarded",total_duplicates_found, total_duplicates_discarded);
4428 textprintf_centre_ex(status,font,120,76,jwin_pal[jcTEXTFG],-1,"%d normal %s",duplicates_found[0],((DuplicateAction[0]<2)?"found":"discarded"));
4429 textprintf_centre_ex(status,font,120,86,jwin_pal[jcTEXTFG],-1,"%d flipped (h) %s",duplicates_found[1],((DuplicateAction[1]<2)?"found":"discarded"));
4430 textprintf_centre_ex(status,font,120,96,jwin_pal[jcTEXTFG],-1,"%d flipped (v) %s",duplicates_found[2],((DuplicateAction[2]<2)?"found":"discarded"));
4431 textprintf_centre_ex(status,font,120,106,jwin_pal[jcTEXTFG],-1,"%d flipped (hv) %s",duplicates_found[3],((DuplicateAction[3]<2)?"found":"discarded"));
4432 textprintf_centre_ex(status,font,120,128,jwin_pal[jcTEXTFG],-1,"Press any key to stop.");
4433 blit(status,screen,0, 0, 40, 20, 240, 140);
4434 SCRFIX();
4435 }
4436
4437 canadd=true;
4438
4439 if(currtile>=NEWMAXTILES) //if we've maxed out on our tiles...
4440 {
4441 delete[] testtile;
4442 return true;
4443 }
4444
4445 switch(imagetype)
4446 {
4447 case ftBIN:
4448 break;
4449
4450 case ftZGP:
4451 case ftQST:
4452 case ftZQT:
4453 case ftQSU:
4454 case ftTIL:
4455 memset(testtile, 0, tilesize(tf32Bit));
4456 imported_format=grabtilebuf[tx].format;
4457
4458 switch(cdepth)
4459 {
4460 case 1: //4-bit
4461 newformat=tf4Bit;
4462
4463 switch(imported_format)
4464 {
4465 case tf4Bit:
4466 case tf8Bit:
4467 for(int32_t y=0; y<16; y++) //snag a tile
4468 {
4469 for(int32_t x=0; x<16; x+=2)
4470 {
4471 testtile[(y*8)+(x/2)]=
4472 (grabtilebuf[tx].data[y*16+x]&15)+
4473 ((grabtilebuf[tx].data[y*16+x+1]&15)<<4);
4474 }
4475 }
4476
4477 break;
4478 }
4479
4480 break;
4481
4482 case 2: //8-bit
4483 newformat=tf8Bit;
4484
4485 switch(imported_format)
4486 {
4487 case tf4Bit:
4488 unpack_tile(grabtilebuf, tx, 0, true);
4489 cst = cs&15;
4490 cst <<= CSET_SHFT;
4491
4492 for(int32_t i=0; i<256; i++)
4493 {
4494 if(!shift||unpackbuf[i]!=0)
4495 {
4496 unpackbuf[i]+=cst;
4497 }
4498 }
4499
4500 pack_tiledata(testtile, unpackbuf, tf8Bit);
4501 break;
4502
4503 case tf8Bit:
4504 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4505 break;
4506 }
4507
4508 break;
4509
4510 case 3: //original tile's bit depth
4511 newformat=imported_format;
4512 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4513 break;
4514 }
4515
4516 break;
4517
4518 case ftBMP:
4519 newformat=cdepth;
4520
4521 for(int32_t y=0; y<16; y++) //snag a tile
4522 {
4523 for(int32_t x=0; x<16; x+=2)
4524 {
4525 testtile[(y*16)+x]=getpixel(((BITMAP*)imagebuf),(tx*16)+x,(ty*16)+y);
4526 testtile[(y*16)+x+1]=getpixel(((BITMAP*)imagebuf),(tx*16)+x+1,(ty*16)+y);
4527 }
4528 }
4529
4530 break;
4531 }
4532
4533 if(DuplicateAction[0]+DuplicateAction[1]+DuplicateAction[2]+DuplicateAction[3]>0)
4534 {
4535 temp_canadd=true;
4536
4537 //check all tiles before this one
4538 for(int32_t checktile=((OnlyCheckNewTilesForDuplicates!=0)?start:0); ((temp_canadd==true)&&(checktile<currtile)); checktile++)
4539 {
4540 for(int32_t flipping=0; ((temp_canadd==true)&&(flipping<4)); ++flipping)
4541 {
4542 if(DuplicateAction[flipping]>0)
4543 {
4544 if(keypressed())
4545 {
4546 delete[] testtile;
4547 return true;
4548 }
4549
4550 duplicate=(newformat==imported_format);
4551
4552 if(duplicate)
4553 {
4554 switch(flipping)
4555 {
4556 case 0: //normal
4557 if(dest[checktile].data!=NULL)
4558 {
4559 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4560 {
4561 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4562 {
4563 // if ((dest[(checktile*128)+(y*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4564 if((dest[checktile].data[(y*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4565 {
4566 duplicate=false;
4567 }
4568 }
4569 }
4570 }
4571
4572 break;
4573
4574 case 1: //horizontal
4575 if(dest[checktile].data!=NULL)
4576 {
4577 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4578 {
4579 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4580 {
4581 // if ((dest[(checktile*128)+(y*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4582 if((dest[checktile].data[(y*8*newformat)+(14+(newformat-1)-x)/(3-newformat)])!=testtile[(y*16)+x])
4583 {
4584 duplicate=false;
4585 }
4586 }
4587 }
4588 }
4589
4590 break;
4591
4592 case 2: //vertical
4593 if(dest[checktile].data!=NULL)
4594 {
4595 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4596 {
4597 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4598 {
4599 // if ((dest[(checktile*128)+((15-y)*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4600 if((dest[checktile].data[((15-y)*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4601 {
4602 duplicate=false;
4603 }
4604 }
4605 }
4606 }
4607
4608 break;
4609
4610 case 3: //both
4611 if(dest[checktile].data!=NULL)
4612 {
4613 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4614 {
4615 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4616 {
4617 // if ((dest[(checktile*128)+((15-y)*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4618 if((dest[checktile].data[((15-y)*8*newformat)+((14+(newformat-1)-x)/(3-newformat))])!=testtile[(y*16)+x])
4619 {
4620 duplicate=false;
4621 }
4622 }
4623 }
4624 }
4625
4626 break;
4627 }
4628 }
4629
4630 if(duplicate==true)
4631 {
4632 ++duplicates_found[flipping];
4633 ++total_duplicates_found;
4634
4635 if(DuplicateAction[flipping]>1)
4636 {
4637 ++total_duplicates_discarded;
4638 temp_canadd=false;
4639 }
4640 }
4641 }
4642
4643 canadd=canadd&&temp_canadd;
4644 }
4645 }
4646 }
4647
4648 // dest[currtile].format=(cdepth==3?imported_format:cdepth);
4649 dest[currtile].format=newformat;
4650
4651 if(dest[currtile].data!=NULL)
4652 {
4653 free(dest[currtile].data);
4654 }
4655
4656 dest[currtile].data=(byte *)malloc(tilesize(dest[currtile].format));
4657
4658 if(dest[currtile].data==NULL)
4659 {
4660 Z_error_fatal("Unable to initialize tile #%d.\n", currtile);
4661 }
4662
4663 if(canadd==true)
4664 {
4665 /*
4666 for(int32_t y=0; y<16; y++)
4667 {
4668 for(int32_t x=0; x<8; x++)
4669 {
4670 dest[currtile].data[(y*8)+x]=testtile[(y*8)+x];
4671 }
4672 }
4673 */
4674 memcpy(dest[currtile].data, testtile, tilesize(dest[currtile].format));
4675 ++currtile;
4676 }
4677 }
4678 }
4679
4680 destroy_bitmap(status);
4681 delete[] testtile;
4682 return true;
4683 }
4684
4685 void grab(byte(*dest)[256],byte *def, int32_t width, int32_t height, int32_t oformat, byte *newformat)
4686 {
4687 byte defFormat=(bp==8) ? tf8Bit : tf4Bit;
4688 byte format=defFormat;
4689 int32_t stile = ((imagey*TILES_PER_ROW)+imagex)+(((sely/16)*TILES_PER_ROW)+(selx/16));
4690
4691 switch(imagetype)
4692 {
4693 case ftZGP:
4694 case ftQST:
4695 case ftZQT:
4696 case ftQSU:
4697 case ftTIL:
4698 case ftBIN:
4699 case ftBMP:
4700 for(int32_t ty=0; ty<height; ty++)
4701 {
4702 for(int32_t tx=0; tx<width; tx++)
4703 {
4704 format=defFormat;
4705 switch(imagetype)
4706 {
4707 case ftZGP:
4708 case ftQST:
4709 case ftZQT:
4710 case ftQSU:
4711 case ftTIL:
4712 format=grabtilebuf[stile+((ty*TILES_PER_ROW)+tx)].format;
4713 break;
4714 }
4715
4716 bool ever_did_unmasked = false;
4717
4718 for(int32_t y=0; y<16; y++)
4719 {
4720 for(int32_t x=0; x<16; x+=2)
4721 {
4722 bool masked = (y<8 && x<8 && grabmask&1) || (y<8 && x>7 && grabmask&2) || (y>7 && x<8 && grabmask&4) || (y>7 && x>7 && grabmask&8);
4723 if (masked)
4724 {
4725 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*16)+(x)];
4726 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*16)+(x+1)];
4727 }
4728 else
4729 {
4730 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x]=getpixel(screen2,(tx*16)+x+selx,(ty*16)+y+sely);
4731 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1]=getpixel(screen2,(tx*16)+x+1+selx,(ty*16)+y+sely);
4732 ever_did_unmasked = true;
4733 }
4734 if (format == tf4Bit)
4735 {
4736 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x] &= 15;
4737 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1] &= 15;
4738 }
4739 }
4740 }
4741
4742 if (ever_did_unmasked)
4743 newformat[(ty*TILES_PER_ROW)+tx] = format;
4744 }
4745 }
4746
4747 break;
4748
4749 default:
4750 for(int32_t i=0; i<200; i++)
4751 {
4752 for(int32_t j=0; j<256; j++)
4753 {
4754 dest[i][j]=0;
4755 }
4756
4757 newformat[i] = tf4Bit;
4758 }
4759
4760 break;
4761 }
4762 }
4763
4764 static void scale_imagebuf_bitmap()
4765 {
4766 imagebuf_bitmap_scale = std::clamp(imagebuf_bitmap_scale, -10, 10);
4767
4768 float scale = IMAGEBUF_SCALE;
4769 int nw = original_imagebuf_bitmap->w * scale;
4770 int nh = original_imagebuf_bitmap->h * scale;
4771 if (nw <= 0 || nh <= 0)
4772 return;
4773
4774 BITMAP* scaled_bmp = create_bitmap_ex(8, nw, nh);
4775 if (!scaled_bmp)
4776 return;
4777
4778 stretch_blit(original_imagebuf_bitmap, scaled_bmp, 0, 0, original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, 0, 0, nw, nh);
4779 if (imagebuf != original_imagebuf_bitmap)
4780 destroy_bitmap((BITMAP*)imagebuf);
4781 imagebuf = scaled_bmp;
4782 }
4783
4784 //Grabber is not grabbing to tile pages beyond pg. 252 right now. -ZX 18th June, 2019
4785 void grab_tile(int32_t tile,int32_t &cs)
4786 {
4787 zq_allow_tile_draw_cache = true;
4788
4789 int window_w = 640+6+6, window_h = 480+25+6;
4790 int window_x=(zq_screen_w-window_w)/2;
4791 int window_y=(zq_screen_h-window_h)/2;
4792 popup_zqdialog_start(window_x,window_y,window_w,window_h,-1);
4793 int window_xofs = 0;
4794 int screen_xofs=6;
4795 int screen_yofs=25;
4796 int panel_yofs=0;
4797 int bwidth = 61*1.5;
4798 int bheight = 20*1.5;
4799 int button_x = 255*2;
4800 int grab_ok_button_y = 168*2 + 32;
4801 int leech_button_x = 117*2;
4802 int leech_button_y = 166*2 + 32;
4803 int grab_cancel_button_y = 192*2 + 32;
4804 int file_button_y = 216*2 + 32;
4805 int rec_button_x = 117*2;
4806 int rec_button_y = 192*2 + 32;
4807
4808 int screen_y1 = 24;
4809 int screen_y2 = screen_y1+320-1;
4810
4811 int crect_x = 184+190;
4812 int crect_y = 168*2 + 32;
4813 int crect_w = 8*2;
4814 int crect_h = 8*2;
4815
4816 int xrect_x = 640 + 12 - 21;
4817 int xrect_y = 5;
4818
4819 byte newtile[200][256];
4820 BITMAP *screen3=create_bitmap_ex(8, zq_screen_w, zq_screen_h);
4821 clear_bitmap(screen3);
4822 byte newformat[200];
4823
4824 memset(newtile, 0, 200*256);
4825 memset(newformat, 0, 200);
4826
4827 static EXT_LIST list[] =
4828 {
4829 { (char *)"All Files (*.*)", NULL },
4830 { (char *)"Bitmap Image (*.bmp)", (char *)"bmp" },
4831 { (char *)"GIF Image (*.gif)", (char *)"gif" },
4832 { (char *)"JPEG Image (*.jpg, *.jpeg)", (char *)"jpg,jpeg" },
4833 { (char *)"ZC Tile Export (*.til)", (char *)"til" },
4834 { (char *)"ZC Quest Template (*.zqt)", (char *)"zqt" },
4835 { (char *)"ZC Quest (*.qst)", (char *)"qst" },
4836 { (char *)"ZC Graphics Pack (*.zgp)", (char *)"zgp" },
4837 { (char *)"ZC Unencoded Quest (*.qsu)", (char *)"qsu" },
4838 { (char *)"NES ROM Image (*.nes)", (char *)"nes" },
4839 { (char *)"SNES ROM Image (*.smc)", (char *)"smc" },
4840 { (char *)"Gameboy ROM Image (*.gb)", (char *)"gb" },
4841 { (char *)"Gameboy Advance ROM Image (*.gba)", (char *)"gba" },
4842 { NULL, NULL }
4843 };
4844
4845
4846 memset(cset_reduce_table, 0, 256);
4847 memset(col_diff,0,3*128);
4848 bool bdown=false;
4849 int done=0;
4850 int pal=0;
4851 int f=0;
4852 int black=vc(0),white=vc(15);
4853 int selwidth=1, selheight=1;
4854 int selx2=0, sely2=0;
4855 bool xreversed=false, yreversed=false;
4856 bool doleech=false, dofile=false, dopal=false;
4857
4858 int jwin_pal2[jcMAX];
4859 memcpy(jwin_pal2, jwin_pal, sizeof(int)*jcMAX);
4860
4861
4862 if(imagebuf==NULL)
4863 load_imagebuf();
4864
4865 calc_cset_reduce_table(imagepal, cs);
4866 calc_cset_reduce_table_8bit(imagepal);
4867 draw_grab_window();
4868 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
4869 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
4870
4871 while(gui_mouse_b())
4872 {
4873 /* do nothing */
4874 rest(1);
4875 }
4876
4877 do
4878 {
4879 HANDLE_CLOSE_ZQDLG();
4880 if(exiting_program) break;
4881 rest(4);
4882 bool redraw=false;
4883
4884 if(keypressed())
4885 {
4886 redraw=true;
4887
4888 switch(readkey()>>8)
4889 {
4890 case KEY_F:
4891 dofile=true;
4892 break;
4893
4894 case KEY_L:
4895 doleech=true;
4896 break;
4897
4898 case KEY_P:
4899 if(imagetype==ftBMP)
4900 {
4901 dopal=true;
4902 recolor=rcNone;
4903 calc_cset_reduce_table(imagepal, cs);
4904 }
4905
4906 break;
4907
4908 case KEY_ESC:
4909 done=1;
4910 break;
4911
4912 case KEY_ENTER_PAD:
4913 case KEY_ENTER:
4914 done=2;
4915 break;
4916
4917 case KEY_DOWN:
4918 if(CHECK_CTRL_CMD) sely=zc_min(sely+1,144);
4919 else ++imagey;
4920
4921 break;
4922
4923 case KEY_UP:
4924 if(CHECK_CTRL_CMD) sely=zc_max(sely-1,0);
4925 else --imagey;
4926
4927 break;
4928
4929 case KEY_RIGHT:
4930 if(CHECK_CTRL_CMD) selx=zc_min(selx+1,304);
4931 else ++imagex;
4932
4933 break;
4934
4935 case KEY_LEFT:
4936 if(CHECK_CTRL_CMD) selx=zc_max(selx-1,0);
4937 else --imagex;
4938
4939 break;
4940
4941 case KEY_PGDN:
4942 imagey+=10;
4943 break;
4944
4945 case KEY_PGUP:
4946 imagey-=10;
4947 break;
4948
4949 case KEY_HOME:
4950 imagex=imagey=0;
4951 break;
4952
4953 case KEY_EQUALS:
4954 case KEY_PLUS_PAD:
4955 cs = (cs<13) ? cs+1:0;
4956 if(recolor==rc4Bit)
4957 calc_cset_reduce_table(imagepal, cs);
4958 break;
4959
4960 case KEY_MINUS:
4961 case KEY_MINUS_PAD:
4962 cs = (cs>0) ? cs-1:13;
4963 if(recolor==rc4Bit)
4964 calc_cset_reduce_table(imagepal, cs);
4965 break;
4966
4967 case KEY_S:
4968 if(grabmode==1) grabmode=8;
4969 else if(grabmode==8) grabmode=16;
4970 else grabmode=1;
4971
4972 break;
4973
4974 case KEY_COMMA:
4975 if (imagetype == ftBMP)
4976 {
4977 imagebuf_bitmap_scale--;
4978 if (imagebuf_bitmap_scale == 0)
4979 imagebuf_bitmap_scale = -2;
4980 scale_imagebuf_bitmap();
4981 }
4982 break;
4983 case KEY_STOP:
4984 if (imagetype == ftBMP)
4985 {
4986 imagebuf_bitmap_scale++;
4987 if (imagebuf_bitmap_scale == -1)
4988 imagebuf_bitmap_scale = 1;
4989 scale_imagebuf_bitmap();
4990 }
4991 break;
4992
4993 case KEY_1:
4994 if(recolor==rc8Bit)
4995 recolor=rcNone;
4996 //imagex=(imagex*bp)>>3;
4997 bp=1;
4998 //imagex<<=3;
4999 nesmode=false;
5000 break;
5001
5002 case KEY_2:
5003 if(recolor==rc8Bit)
5004 recolor=rcNone;
5005 //imagex=(imagex*bp)>>3;
5006 bp=2;
5007 //imagex<<=2;
5008 nesmode=false;
5009 break;
5010
5011 case KEY_N:
5012 if(recolor==rc8Bit)
5013 recolor=rcNone;
5014 //imagex=(imagex*bp)>>3;
5015 bp=2;
5016 //imagex<<=2;
5017 nesmode=true;
5018 break;
5019
5020 case KEY_4:
5021 if(recolor==rc8Bit)
5022 recolor=rcNone;
5023 //imagex=(imagex*bp)>>3;
5024 bp=4;
5025 //imagex<<=1;
5026 nesmode=false;
5027 break;
5028
5029 case KEY_8:
5030 //imagex=(imagex*bp)>>3;
5031 bp=8;
5032 break;
5033
5034 case KEY_B:
5035 if(bp==2&&!nesmode)
5036 {
5037 nesmode=true;
5038 }
5039 else
5040 {
5041 nesmode=false;
5042 bp<<=1;
5043
5044 if(bp==16)
5045 {
5046 bp=1;
5047 //imagex<<=3;
5048 }
5049 else
5050 {
5051 //imagex>>=1;
5052 }
5053 }
5054
5055 break;
5056
5057 case KEY_M:
5058 romtilemode=(romtilemode+1)%4;
5059 break;
5060
5061 case KEY_Z:
5062 if(romofs>0) --romofs;
5063
5064 break;
5065
5066 case KEY_X:
5067 ++romofs;
5068 break;
5069
5070 case KEY_R:
5071 if(pal)
5072 {
5073 dopal=true;
5074 }
5075
5076 if(recolor!=rcNone)
5077 recolor=rcNone;
5078 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5079 {
5080 bp=8;
5081 recolor=rc8Bit;
5082 calc_cset_reduce_table_8bit(imagepal);
5083 }
5084 else
5085 {
5086 if(bp==8)
5087 bp=4;
5088 recolor=rc4Bit;
5089 calc_cset_reduce_table(imagepal, cs);
5090 }
5091 break;
5092
5093 default:
5094 redraw=false;
5095 }
5096
5097 clear_keybuf();
5098
5099 if(imagex<0) imagex=0;
5100
5101 if(imagey<0) imagey=0;
5102
5103 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5104 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5105 }
5106
5107 //boogie!
5108 if(gui_mouse_b()==1 && !bdown)
5109 {
5110 int x=gui_mouse_x();
5111 int y=gui_mouse_y();
5112 if(isinRect(x,y,xrect_x, xrect_y, xrect_x + 15, xrect_y + 13))
5113 if(do_x_button(screen, xrect_x, xrect_y))
5114 done=1;
5115
5116 if(!bdown)
5117 {
5118 bool regrab=false;
5119 bdown=true;
5120 FONT* oldfont = font;
5121 font = get_zc_font(font_lfont_l);
5122
5123 if(y>=screen_y1 && y<=screen_y2)
5124 {
5125 do
5126 {
5127 HANDLE_CLOSE_ZQDLG();
5128 if(exiting_program) break;
5129 int x = (gui_mouse_x()-screen_xofs) / 2;
5130 int y = (gui_mouse_y()-screen_yofs) / 2;
5131
5132 int ox=selx,oy=sely,ow=selwidth,oh=selheight;
5133
5134 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
5135 {
5136 selx=vbound((x/grabmode)*grabmode,0,304);
5137 sely=vbound((y/grabmode)*grabmode,0,144);
5138 selx2=selx;
5139 sely2=sely;
5140 selwidth=1;
5141 selheight=1;
5142 xreversed=false;
5143 yreversed=false;
5144 }
5145 else
5146 {
5147 if(xreversed)
5148 {
5149 zc_swap(selx, selx2);
5150 xreversed=false;
5151 }
5152
5153 if(yreversed)
5154 {
5155 zc_swap(sely, sely2);
5156 yreversed=false;
5157 }
5158
5159 selx2=vbound((x/grabmode)*grabmode,0,304);
5160 sely2=vbound((y/grabmode)*grabmode,0,144);
5161 selwidth=1+(abs(selx2-selx))/16;
5162 selheight=1+(abs(sely2-sely))/16;
5163
5164 if(selx2<selx)
5165 {
5166 zc_swap(selx, selx2);
5167 xreversed=true;
5168 }
5169
5170 if(sely2<sely)
5171 {
5172 zc_swap(sely, sely2);
5173 yreversed=true;
5174 }
5175 }
5176
5177 bool changed = (ox!=selx || oy!=sely || ow!=selwidth || oh!=selheight);
5178 bool redraw = changed || !(f%8);
5179
5180 if(redraw)
5181 {
5182 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5183 if(changed)
5184 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5185 if(f&8)
5186 {
5187 static const int w = 32;
5188 rect(screen,(selx*2)+screen_xofs,(sely*2)+screen_yofs,(selx*2)+screen_xofs+((selwidth-1)*w)+(w-1),(sely*2)+screen_yofs+((selheight-1)*w)+(w-1),white);
5189 }
5190 }
5191 else custom_vsync();
5192
5193 ++f;
5194 }
5195 while(gui_mouse_b());
5196 }
5197 else if(isinRect(x,y,button_x,grab_ok_button_y,button_x+bwidth,grab_ok_button_y+bheight))
5198 {
5199 if(do_text_button(button_x,grab_ok_button_y,bwidth,bheight,"OK"))
5200 done=2;
5201 }
5202 else if(isinRect(x,y,leech_button_x,leech_button_y,leech_button_x+bwidth,leech_button_y+bheight))
5203 {
5204 if(do_text_button(leech_button_x,leech_button_y,bwidth,bheight,"Leech"))
5205 {
5206 doleech=true;
5207 }
5208 }
5209 else if(isinRect(x,y,button_x,grab_cancel_button_y,button_x+bwidth,grab_cancel_button_y+bheight))
5210 {
5211 if(do_text_button(button_x,grab_cancel_button_y,bwidth,bheight,"Cancel"))
5212 done=1;
5213 }
5214 else if(isinRect(x,y,button_x,file_button_y,button_x+bwidth,file_button_y+bheight))
5215 {
5216 if(do_text_button(button_x,file_button_y,bwidth,bheight,"File"))
5217 {
5218 dofile=true;
5219 }
5220 }
5221 else if(imagetype == ftBMP && isinRect(x,y,rec_button_x, rec_button_y, rec_button_x+bwidth, rec_button_y+bheight))
5222 {
5223 if(do_text_button(rec_button_x,rec_button_y,bwidth,bheight,"Recolor"))
5224 {
5225 if(pal)
5226 {
5227 dopal = true;
5228 }
5229
5230 if(recolor!=rcNone)
5231 recolor=rcNone;
5232 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5233 {
5234 bp=8;
5235 recolor=rc8Bit;
5236 calc_cset_reduce_table_8bit(imagepal);
5237 }
5238 else
5239 {
5240 if(bp==8)
5241 bp=4;
5242 recolor=rc4Bit;
5243 calc_cset_reduce_table(imagepal, cs);
5244 }
5245 redraw=true;
5246 }
5247 }
5248 else if(isinRect(x,y+panel_yofs,crect_x,crect_y,crect_x+(16),crect_y+crect_h-1))
5249 {
5250 regrab=true;
5251 grabmask^=1;
5252 }
5253 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y,crect_x+(32)-1,crect_y+crect_h-1))
5254 {
5255 regrab=true;
5256 grabmask^=2;
5257 }
5258 else if(isinRect(x,y+panel_yofs,crect_x,crect_y+crect_h,crect_x+(16)-1,crect_y+crect_h+crect_h-1))
5259 {
5260 regrab=true;
5261 grabmask^=4;
5262 }
5263 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y+crect_h,crect_x+(32)-1,crect_y+crect_h+crect_h-1))
5264 {
5265 regrab=true;
5266 grabmask^=8;
5267 }
5268
5269 if(regrab)
5270 {
5271 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5272 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5273 redraw=true;
5274 }
5275
5276 font = oldfont;
5277 }
5278 }
5279
5280 if(gui_mouse_b()==0)
5281 bdown=false;
5282
5283 if(dofile)
5284 {
5285 if (prompt_for_existing_file_compat("Load File", "", list, imagepath, true))
5286 {
5287 zc_set_palette(RAMpal);
5288 pal=0;
5289 white=vc(15);
5290 black=vc(0);
5291 strcpy(imagepath,temppath);
5292 load_imagebuf();
5293 imagex=imagey=0;
5294 calc_cset_reduce_table(imagepal, cs);
5295 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5296 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5297 }
5298
5299 while(key[KEY_ESC])
5300 {
5301 poll_keyboard();
5302 /* do nothing */
5303 rest(1);
5304 }
5305
5306 clear_keybuf();
5307 dofile=false;
5308 redraw=true;
5309 }
5310
5311 if(doleech)
5312 {
5313 if(leech_tiles(newtilebuf,tile,cs))
5314 {
5315 done=1;
5316 }
5317 else
5318 {
5319 while(key[KEY_ESC])
5320 {
5321 poll_keyboard();
5322 /* do nothing */
5323 rest(1);
5324 }
5325
5326 clear_keybuf();
5327 redraw=true;
5328 }
5329
5330 doleech=false;
5331 }
5332
5333 if(dopal)
5334 {
5335 pal^=1;
5336
5337 if(pal)
5338 {
5339 get_bw(imagepal,black,white);
5340
5341 jwin_pal[jcBOX] =imagepal_table.data[0][jwin_pal[jcBOX]];
5342 jwin_pal[jcLIGHT] =imagepal_table.data[0][jwin_pal[jcLIGHT]];
5343 jwin_pal[jcMEDLT] =imagepal_table.data[0][jwin_pal[jcMEDLT]];
5344 jwin_pal[jcMEDDARK]=imagepal_table.data[0][jwin_pal[jcMEDDARK]];
5345 jwin_pal[jcDARK] =imagepal_table.data[0][jwin_pal[jcDARK]];
5346 jwin_pal[jcBOXFG] =imagepal_table.data[0][jwin_pal[jcBOXFG]];
5347 jwin_pal[jcTITLEL] =imagepal_table.data[0][jwin_pal[jcTITLEL]];
5348 jwin_pal[jcTITLER] =imagepal_table.data[0][jwin_pal[jcTITLER]];
5349 jwin_pal[jcTITLEFG]=imagepal_table.data[0][jwin_pal[jcTITLEFG]];
5350 jwin_pal[jcTEXTBG] =imagepal_table.data[0][jwin_pal[jcTEXTBG]];
5351 jwin_pal[jcTEXTFG] =imagepal_table.data[0][jwin_pal[jcTEXTFG]];
5352 jwin_pal[jcSELBG] =imagepal_table.data[0][jwin_pal[jcSELBG]];
5353 jwin_pal[jcSELFG] =imagepal_table.data[0][jwin_pal[jcSELFG]];
5354 gui_bg_color=jwin_pal[jcBOX];
5355 gui_fg_color=jwin_pal[jcBOXFG];
5356 jwin_set_colors(jwin_pal);
5357 }
5358 else
5359 {
5360 white=vc(15);
5361 black=vc(0);
5362
5363 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5364 gui_bg_color=jwin_pal[jcBOX];
5365 gui_fg_color=jwin_pal[jcBOXFG];
5366 jwin_set_colors(jwin_pal);
5367 }
5368
5369 zc_set_palette_range(pal?imagepal:RAMpal,0,255,false);
5370
5371 dopal=false;
5372 redraw=true;
5373 }
5374
5375 if(redraw)
5376 {
5377 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5378 }
5379 else
5380 {
5381 custom_vsync();
5382 }
5383
5384 if((f%8)==0)
5385 {
5386 stretch_blit(screen2,screen3,0, 0, zq_screen_w, zq_screen_h, 0, 0, zq_screen_w*2, zq_screen_h*2);
5387
5388 int selxl = selx* 2;
5389 int selyl = sely* 2;
5390 int w = 32;
5391
5392 if(f&8)
5393 rect(screen3,selxl,selyl,selxl+((selwidth-1)*w)+(w-1),selyl+((selheight-1)*w)+(w-1),white);
5394
5395 blit(screen3,screen,selxl,selyl,selxl+screen_xofs,selyl+screen_yofs,selwidth*w,selheight*w);
5396 }
5397
5398 // SCRFIX();
5399 ++f;
5400
5401 }
5402 while(!done);
5403
5404 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5405 gui_bg_color=jwin_pal[jcBOX];
5406 gui_fg_color=jwin_pal[jcBOXFG];
5407 jwin_set_colors(jwin_pal);
5408
5409
5410 if(done==2)
5411 {
5412 go_tiles();
5413 saved=false;
5414
5415 for(int y=0; y<selheight; y++)
5416 {
5417 for(int x=0; x<selwidth; x++)
5418 {
5419 int temptile=tile+((TILES_PER_ROW*y)+x);
5420 int format=(bp==8) ? tf8Bit : tf4Bit;
5421
5422 if(newtilebuf[temptile].data!=NULL)
5423 free(newtilebuf[temptile].data);
5424
5425 newtilebuf[temptile].format=format;
5426 newtilebuf[temptile].data=(byte *)malloc(tilesize(format));
5427
5428 if(newtilebuf[temptile].data==NULL)
5429 {
5430 Z_error_fatal("Unable to initialize tile #%d.\n", temptile);
5431 break;
5432 }
5433
5434 for(int i=0; i<256; i++)
5435 {
5436 // newtilebuf[temptile].data[i] = cset_reduce_table[newtile[(TILES_PER_ROW*y)+x][i]];
5437 newtilebuf[temptile].data[i] = newtile[(TILES_PER_ROW*y)+x][i];
5438 }
5439
5440 // unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
5441 }
5442 }
5443 }
5444
5445 destroy_bitmap(screen3);
5446
5447 if(pal)
5448 zc_set_palette(RAMpal);
5449
5450 recolor=rcNone;
5451 calc_cset_reduce_table(imagepal, cs);
5452 register_blank_tiles();
5453 popup_zqdialog_end();
5454
5455 zq_allow_tile_draw_cache = false;
5456 }
5457
5458 int32_t show_only_unused_tiles=4; //1 bit: hide used, 2 bit: hide unused, 4 bit: hide blank
5459 bool tile_is_used(int32_t tile)
5460 {
5461 return used_tile_table[tile];
5462 }
5463 void draw_tiles(int32_t first,int32_t cs, int32_t f)
5464 {
5465 draw_tiles(screen2, first, cs, f, true);
5466 }
5467 void draw_tiles(BITMAP* dest,int32_t first,int32_t cs, int32_t f, bool large, bool true_empty)
5468 {
5469 clear_bitmap(dest);
5470 BITMAP *buf = create_bitmap_ex(8,16,16);
5471
5472 int32_t w = 16;
5473 int32_t h = 16;
5474
5475 if(large)
5476 {
5477 w *=2;
5478 h *=2;
5479 }
5480
5481 for(int32_t i=0; i<TILES_PER_PAGE; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
5482 {
5483 int32_t x = (i%TILES_PER_ROW)<<4;
5484 int32_t y = (i/TILES_PER_ROW)<<4;
5485 int32_t l = 16;
5486
5487 if(large)
5488 {
5489 x*=2;
5490 y*=2;
5491 l*=2;
5492 }
5493
5494 l-=2;
5495
5496 if((HIDE_USED && tile_is_used(first+i) && !blank_tile_table[first+i]) // 1 bit: hide used
5497 || (HIDE_UNUSED && !tile_is_used(first+i) && !blank_tile_table[first+i]) // 2 bit: hide unused
5498 || (HIDE_BLANK && blank_tile_table[first+i])) // 4 bit: hide blank
5499 {
5500 if(!true_empty) //Use pure color 0; no effects
5501 {
5502 if (InvalidBG == 2)
5503 {
5504 draw_checkerboard(dest, x, y, w);
5505 }
5506 else if(InvalidBG == 1)
5507 {
5508 for(int32_t dy=0; dy<=l+1; dy++)
5509 {
5510 for(int32_t dx=0; dx<=l+1; dx++)
5511 {
5512 dest->line[dy+(y)][dx+(x)]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5513 }
5514 }
5515 }
5516 else
5517 {
5518 for(int32_t dy=0; dy<=l+1; dy++)
5519 {
5520 for(int32_t dx=0; dx<=l+1; dx++)
5521 {
5522 dest->line[dy+(y)][dx+(x)]=vc(0);
5523 }
5524 }
5525 rect(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5526 line(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5527 line(dest, (x)+1,(y)+l, (x)+l, (y)+1, vc(15));
5528 }
5529 }
5530 }
5531 else
5532 {
5533 puttile16(buf,first+i,0,0,cs,0);
5534 stretch_blit(buf,dest,0,0,16,16,x,y,w,h);
5535 }
5536
5537 if((f%32)<=16 && large && !HIDE_8BIT_MARKER && newtilebuf[first+i].format==tf8Bit)
5538 {
5539 textprintf_ex(dest,get_zc_font(font_z3smallfont),(x)+l-3,(y)+l-3,vc(int32_t((f%32)/6)+10),-1,"8");
5540 }
5541 }
5542
5543 destroy_bitmap(buf);
5544 }
5545
5546 void tile_info_0(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,bool rect_sel)
5547 {
5548 int32_t yofs=3;
5549 BITMAP *buf = create_bitmap_ex(8,16,16);
5550 int32_t mul = 2;
5551 FONT *tfont = get_zc_font(font_pfont);
5552
5553 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5554 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5555 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5556 tfont = get_zc_font(font_lfont_l);
5557
5558 // Copied tile and numbers
5559 jwin_draw_frame(screen2,(34*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5560 int32_t coldiff=TILECOL(copy)-TILECOL(copy+copycnt-1);
5561 if(copy>=0)
5562 {
5563 puttile16(buf,rect_sel&&coldiff>0?copy-coldiff:copy,0,0,cs,0);
5564 stretch_blit(buf,screen2,0,0,16,16,34*mul,216*mul+yofs,16*mul,16*mul);
5565
5566 if(copycnt>1)
5567 {
5568 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
5569 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
5570 }
5571 else
5572 {
5573 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
5574 }
5575 }
5576 else // No tiles copied
5577 {
5578 if (InvalidBG == 2)
5579 {
5580 draw_checkerboard(screen2, 34 * mul, 216 * mul + yofs, 16 * mul);
5581 }
5582 else if(InvalidBG == 1)
5583 {
5584 for(int32_t dy=0; dy<16*mul; dy++)
5585 {
5586 for(int32_t dx=0; dx<16*mul; dx++)
5587 {
5588 screen2->line[(216*mul+yofs+dy)][36*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5589 }
5590 }
5591 }
5592 else
5593 {
5594 rectfill(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(0));
5595 rect(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5596 line(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5597 line(screen2, 34*mul, ((216+15)*mul)+yofs, (34+15)*mul, (216*mul)+yofs, vc(15));
5598 }
5599 }
5600
5601
5602 // Current tile
5603 jwin_draw_frame(screen2,(104*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5604 puttile16(buf,tile,0,0,cs,0);
5605 stretch_blit(buf,screen2,0,0,16,16,104*mul,216*mul+yofs,16*mul,16*mul);
5606
5607 // Current selection mode
5608 jwin_draw_frame(screen2,(127*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5609 stretch_blit(select_bmp[rect_sel?1:0],screen2,0,0,16,16,127*mul,216*mul+yofs,16*mul,16*mul);
5610
5611 if(tile>tile2)
5612 {
5613 zc_swap(tile,tile2);
5614 }
5615
5616 char tbuf[8];
5617 tbuf[0]=0;
5618
5619 if(tile2!=tile)
5620 {
5621 sprintf(tbuf,"-%d",tile2);
5622 }
5623
5624 // Current tile and CSet text
5625 textprintf_ex(screen2,tfont,55*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cs: %d",cs);
5626 textprintf_right_ex(screen2,tfont,99*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile:");
5627 textprintf_right_ex(screen2,tfont,99*mul,224*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,tbuf);
5628
5629 FONT *tf = font;
5630 font = tfont;
5631
5632 draw_text_button(screen2,150*mul,213*mul+yofs,28*mul,21*mul,"&Grab",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5633 draw_text_button(screen2,(150+28)*mul,213*mul+yofs,28*mul,21*mul,"&Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5634 draw_text_button(screen2,(150+28*2)*mul,213*mul+yofs,28*mul,21*mul,"Export",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5635 draw_text_button(screen2,(150+28*3)*mul,213*mul+yofs,28*mul,21*mul,"Recolor",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5636 draw_text_button(screen2,(150+28*4)*mul,213*mul+yofs,28*mul,21*mul,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5637
5638 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5639 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5640 textprintf_centre_ex(screen2,tfont,(305*mul+4),220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5641 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5642
5643 font = tf;
5644
5645 int32_t w = 640;
5646 int32_t h = 480;
5647 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5648 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5649 int32_t screen_xofs=window_xofs+6;
5650 int32_t screen_yofs=window_yofs+25;
5651
5652 custom_vsync();
5653 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5654 SCRFIX();
5655 destroy_bitmap(buf);
5656 }
5657
5658 void tile_info_1(int32_t oldtile,int32_t oldflip,int32_t oldcs,int32_t tile,int32_t flip,int32_t cs,int32_t copy,int32_t page, bool always_use_flip)
5659 {
5660 int32_t yofs=3;
5661 BITMAP *buf = create_bitmap_ex(8,16,16);
5662 int32_t mul = 2;
5663 FONT *tfont = get_zc_font(font_pfont);
5664
5665 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5666 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5667 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5668 tfont = get_zc_font(font_lfont_l);
5669
5670 jwin_draw_frame(screen2,(124*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5671
5672 if(copy>=0)
5673 {
5674 puttile16(buf,copy,0,0,cs,flip);
5675 stretch_blit(buf,screen2,0,0,16,16,124*mul,216*mul+yofs,16*mul,16*mul);
5676 }
5677 else
5678 {
5679 if (InvalidBG == 2)
5680 {
5681 draw_checkerboard(screen2, 124 * mul, 216 * mul + yofs, 16 * mul);
5682 }
5683 else if(InvalidBG == 1)
5684 {
5685 for(int32_t dy=0; dy<16*mul; dy++)
5686 {
5687 for(int32_t dx=0; dx<16*mul; dx++)
5688 {
5689 screen2->line[216*mul+yofs+dy][124*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5690 }
5691 }
5692 }
5693 else
5694 {
5695 rectfill(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(0));
5696 rect(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5697 line(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5698 line(screen2, 124*mul, ((216+15)*mul)+yofs, (124+15)*mul, (216*mul)+yofs, vc(15));
5699 }
5700 }
5701
5702 jwin_draw_frame(screen2,(8*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5703 puttile16(buf,oldtile,0,0, oldcs, oldflip);
5704 stretch_blit(buf,screen2,0,0,16,16,8*mul,216*mul+yofs,16*mul,16*mul);
5705
5706 textprintf_right_ex(screen2,tfont,56*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Old Tile:");
5707 textprintf_ex(screen2,tfont,60*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldtile);
5708
5709 textprintf_right_ex(screen2,tfont,56*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5710 textprintf_ex(screen2,tfont,60*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldcs);
5711
5712 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5713 {
5714 textprintf_right_ex(screen2,tfont,56*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5715 textprintf_ex(screen2,tfont,60*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldflip);
5716 }
5717
5718 jwin_draw_frame(screen2,(148*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5719 puttile16(buf,tile,0,0, cs,
5720 (oldflip>0 || always_use_flip)?flip:0); // Suppress Flip for this usage
5721 stretch_blit(buf,screen2,0,0,16,16,148*mul,216*mul+yofs,16*mul,16*mul);
5722
5723 textprintf_right_ex(screen2,tfont,201*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"New Tile:");
5724 textprintf_ex(screen2,tfont,205*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",tile);
5725 textprintf_right_ex(screen2,tfont,201*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5726 textprintf_ex(screen2,tfont,205*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",cs);
5727
5728 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5729 {
5730 textprintf_right_ex(screen2,tfont,201*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5731 textprintf_ex(screen2,tfont,205*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",flip);
5732 }
5733
5734 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5735 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5736 textprintf_centre_ex(screen2,tfont,309*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5737 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5738
5739
5740 int32_t w = 640;
5741 int32_t h = 480;
5742 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5743 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5744 int32_t screen_xofs=window_xofs+6;
5745 int32_t screen_yofs=window_yofs+25;
5746
5747 custom_vsync();
5748 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5749 SCRFIX();
5750 destroy_bitmap(buf);
5751 }
5752 /*
5753 void reset_tile(tiledata *buf, int32_t t, int32_t format=1)
5754 {
5755 buf[t].format=format;
5756 if (buf[t].data!=NULL)
5757 {
5758 free(buf[t].data);
5759 }
5760 buf[t].data=(byte *)malloc(tilesize(buf[t].format));
5761 if (buf[t].data==NULL)
5762 {
5763 Z_error_fatal("Unable to initialize tile #%d.\n", t);
5764 }
5765 for(int32_t i=0; i<tilesize(buf[t].format); i++)
5766 {
5767 buf[t].data[i]=0;
5768 }
5769 }
5770 */
5771
5772 int32_t hide_used()
5773 {
5774 show_only_unused_tiles ^= 1;
5775 return D_O_K;
5776 }
5777 int32_t hide_unused()
5778 {
5779 show_only_unused_tiles ^= 2;
5780 return D_O_K;
5781 }
5782 int32_t hide_blank()
5783 {
5784 show_only_unused_tiles ^= 4;
5785 return D_O_K;
5786 }
5787 int32_t hide_8bit_marker()
5788 {
5789 show_only_unused_tiles ^= 8;
5790 return D_O_K;
5791 }
5792
5793 enum
5794 {
5795 MENUID_SELTILE_VIEW_HIDE_USED,
5796 MENUID_SELTILE_VIEW_HIDE_UNUSED,
5797 MENUID_SELTILE_VIEW_HIDE_BLANK,
5798 MENUID_SELTILE_VIEW_HIDE_8BIT,
5799 };
5800
1/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 static NewMenu select_tile_view_menu
5801 60 {
5802
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide Used", hide_used, MENUID_SELTILE_VIEW_HIDE_USED },
5803
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide Unused", hide_unused, MENUID_SELTILE_VIEW_HIDE_UNUSED },
5804
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide Blank", hide_blank, MENUID_SELTILE_VIEW_HIDE_BLANK },
5805
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide 8-bit marker", hide_8bit_marker, MENUID_SELTILE_VIEW_HIDE_8BIT },
5806 };
5807
5808 12 static std::function<void(int)> select_tile_color_depth_cb;
5809
5810 static void set_tile_color_depth_4()
5811 {
5812 select_tile_color_depth_cb(tf4Bit);
5813 }
5814 static void set_tile_color_depth_8()
5815 {
5816 select_tile_color_depth_cb(tf8Bit);
5817 }
5818 enum
5819 {
5820 MENUID_SELTILE_COLOR_DEPTH_4_BIT,
5821 MENUID_SELTILE_COLOR_DEPTH_8_BIT,
5822 };
5823
1/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 static NewMenu select_tile_color_depth_menu
5824 36 {
5825
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "4-bit", set_tile_color_depth_4, MENUID_SELTILE_COLOR_DEPTH_4_BIT },
5826
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "8-bit", set_tile_color_depth_8, MENUID_SELTILE_COLOR_DEPTH_8_BIT },
5827 };
5828
5829 //returns the row the tile is in on its page
5830 int32_t tile_page_row(int32_t tile)
5831 {
5832 return TILEROW(tile)-(TILEPAGE(tile)*TILE_ROWS_PER_PAGE);
5833 }
5834
5835 enum {ti_none, ti_encompass, ti_broken};
5836
5837 //striped check and striped selection
5838 int32_t move_intersection_ss(newcombo &cmb, int32_t selection_first, int32_t selection_last, int32_t offset = 0)
5839 {
5840 int32_t cmb_first = cmb.o_tile;
5841 int32_t cmb_last = cmb.o_tile;
5842 do
5843 {
5844 cmb_last = cmb.tile;
5845 animate(cmb, true);
5846 }
5847 while(cmb.tile != cmb.o_tile);
5848 reset_combo_animation(cmb);
5849 cmb_first += offset;
5850 cmb_last += offset;
5851
5852 if(cmb_first > selection_last || cmb_last < selection_first)
5853 return ti_none;
5854 if(cmb_first >= selection_first && cmb_last <= selection_last)
5855 return ti_encompass;
5856
5857 do
5858 {
5859 if(cmb.tile+offset >= selection_first && cmb.tile+offset <= selection_last)
5860 {
5861 reset_combo_animation(cmb);
5862 return ti_broken; //contained, but non-encompassing.
5863 }
5864 animate(cmb, true);
5865 }
5866 while(cmb.tile != cmb.o_tile);
5867 reset_combo_animation(cmb);
5868 return ti_none;
5869 }
5870 int32_t move_intersection_ss(int32_t check_first, int32_t check_last, int32_t selection_first, int32_t selection_last)
5871 {
5872 // if selection is before or after check...
5873 if((check_first>selection_last)||(selection_first>check_last))
5874 {
5875 return ti_none;
5876 }
5877
5878 // if selection envelopes check
5879 if((selection_first<=check_first)&&(selection_last>=check_last))
5880 {
5881 return ti_encompass; //encompass
5882 }
5883
5884 //everything else is a break
5885 return ti_broken; //intersect
5886 }
5887
5888
5889
5890 //rectangular check and striped selection
5891 int32_t move_intersection_rs(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_first, int32_t selection_last)
5892 {
5893 int32_t ret1=-1, ret2=-1;
5894
5895 for(int32_t i=0; i<check_height; ++i)
5896 {
5897 int32_t check_first=((check_top+i)*TILES_PER_ROW)+check_left;
5898 int32_t check_last=check_first+check_width-1;
5899 ret2=move_intersection_ss(check_first, check_last, selection_first, selection_last);
5900
5901 if(ret2==ti_broken)
5902 {
5903 return ti_broken;
5904 }
5905
5906 ret1=(ret2==ti_encompass?ti_encompass:ret1);
5907 }
5908
5909 if(ret1==ti_encompass)
5910 {
5911 if((TILEROW(selection_first)<=check_top) &&
5912 (TILEROW(selection_last)>=(check_top+check_height-1)))
5913 {
5914 return ti_encompass;
5915 }
5916 else
5917 {
5918 return ti_broken;
5919 }
5920 }
5921
5922 return ti_none;
5923 }
5924
5925
5926 //striped check and rectangular selection
5927 int32_t move_intersection_sr(newcombo &cmb, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height, int32_t offset = 0)
5928 {
5929 if(selection_width < TILES_PER_ROW)
5930 {
5931 int32_t cmb_first = cmb.o_tile;
5932 int32_t cmb_last = cmb.o_tile;
5933 do
5934 {
5935 cmb_last = cmb.tile;
5936 animate(cmb, true);
5937 }
5938 while(cmb.tile != cmb.o_tile);
5939 reset_combo_animation(cmb);
5940 cmb_first += offset;
5941 cmb_last += offset;
5942
5943 if((TILEROW(cmb_first)>=selection_top) &&
5944 (TILEROW(cmb_last)<=selection_top+selection_height-1) &&
5945 (TILECOL(cmb_first)>=selection_left) &&
5946 (TILECOL(cmb_last)<=TILECOL(selection_left+selection_width-1)))
5947 {
5948 return ti_encompass;
5949 }
5950 else if((cmb_last<selection_top*TILES_PER_ROW+selection_left) ||
5951 (cmb_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
5952 {
5953 return ti_none;
5954 }
5955
5956 if(TILEROW(cmb_first) == TILEROW(cmb_last))
5957 {
5958 int32_t firstcol = TILECOL(cmb_first);
5959 int32_t lastcol = TILECOL(cmb_last);
5960
5961 if(lastcol < selection_left || firstcol >= selection_left+selection_width)
5962 return ti_none;
5963 else //handle skip x
5964 {
5965 do
5966 {
5967 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width)
5968 {
5969 reset_combo_animation(cmb);
5970 return ti_broken;
5971 }
5972 animate(cmb, true);
5973 }
5974 while(cmb.tile != cmb.o_tile);
5975 reset_combo_animation(cmb);
5976 return ti_none;
5977 }
5978 }
5979 else //multi-row combo...
5980 {
5981 int32_t row = TILEROW(cmb_first);
5982
5983 do
5984 {
5985 if(row < selection_top || row > selection_top+selection_height-1)
5986 {
5987 //This row isn't in the selection; skip to next row
5988 do
5989 {
5990 animate(cmb,true);
5991 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5992 }
5993 while(TILEROW(cmb.tile) == row);
5994 row = TILEROW(cmb.tile);
5995 continue;
5996 }
5997
5998 //This row IS in the selection; check each tile.
5999 do
6000 {
6001 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width-1)
6002 {
6003 reset_combo_animation(cmb);
6004 return ti_broken;
6005 }
6006 animate(cmb, true);
6007 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
6008 }
6009 while(TILEROW(cmb.tile) == row);
6010 row = TILEROW(cmb.tile);
6011 }
6012 while(cmb.tile != cmb.o_tile);
6013
6014 return ti_none; //...Theoretically unreachable, but if it DOES get here, it's done.
6015 }
6016 }
6017
6018 return move_intersection_ss(cmb, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1, offset);
6019 }
6020 int32_t move_intersection_sr(int32_t check_first, int32_t check_last, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6021 {
6022 if(selection_width < TILES_PER_ROW)
6023 {
6024 if((check_last-check_first+1<=selection_width) &&
6025 (TILEROW(check_first)>=selection_top) &&
6026 (TILEROW(check_last)<=selection_top+selection_height-1) &&
6027 (TILECOL(check_first)>=selection_left) &&
6028 (TILECOL(check_last)<=TILECOL(selection_left+selection_width-1)))
6029 {
6030 return ti_encompass;
6031 }
6032 else if((check_last<selection_top*TILES_PER_ROW+selection_left) ||
6033 (check_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
6034 {
6035 return ti_none;
6036 }
6037
6038 //else if (selection_top*TILES_PER_ROW+selection_left<check_first && (selection_top+1)*TILES_PER_ROW+selection_left>check_last)
6039
6040 //one last base case: the strip we're interested in only lies along one row
6041 if(check_first/TILES_PER_ROW == check_last/TILES_PER_ROW)
6042 {
6043 int32_t cfcol = check_first%TILES_PER_ROW;
6044 int32_t clcol = check_last%TILES_PER_ROW;
6045
6046 if(clcol < selection_left || cfcol >= selection_left+selection_width)
6047 return ti_none;
6048 else
6049 return ti_broken;
6050 }
6051 else
6052 {
6053 //recursively cut the strip into substrips which lie entirely on one row
6054 int32_t currow = check_first/TILES_PER_ROW;
6055 int32_t endrow = check_last/TILES_PER_ROW;
6056 int32_t accum = 0;
6057 accum |= move_intersection_sr(check_first,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6058
6059 for(++currow; currow<endrow; currow++)
6060 {
6061 accum |= move_intersection_sr(currow*TILES_PER_ROW,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6062 }
6063
6064 accum |= move_intersection_sr(currow*TILES_PER_ROW, check_last,selection_left,selection_top,selection_width,selection_height);
6065
6066 if(accum > 0)
6067 return ti_broken;
6068
6069 return ti_none;
6070 }
6071 }
6072
6073 return move_intersection_ss(check_first, check_last, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1);
6074 }
6075
6076 //rectangular check and rectangular selection
6077 int32_t move_intersection_rr(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6078 {
6079 if((check_left>=selection_left) &&
6080 (check_left+check_width<=selection_left+selection_width) &&
6081 (check_top>=selection_top) &&
6082 (check_top+check_height<=selection_top+selection_height))
6083 {
6084 return ti_encompass;
6085 }
6086 else
6087 {
6088 for(int32_t i=check_top; i<check_top+check_height; ++i)
6089 {
6090 if(move_intersection_rs(selection_left, selection_top, selection_width, selection_height, i*TILES_PER_ROW+check_left, i*TILES_PER_ROW+check_left+check_width-1)!=ti_none)
6091 {
6092 return ti_broken;
6093 }
6094 }
6095 }
6096
6097 return ti_none;
6098 }
6099
6100
6101
6102
6103 static DIALOG move_textbox_list_dlg[] =
6104 {
6105 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
6106 12 { jwin_win_proc, 0, 0, 300, 212, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6107 12 { jwin_ctext_proc, 150, 18, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6108 12 { jwin_ctext_proc, 150, 28, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6109 12 { jwin_textbox_proc, 12, 40, 277, 138, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6110 12 { jwin_button_proc, 80, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
6111 12 { jwin_button_proc, 160, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
6112 12 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
6113 12 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
6114 };
6115
6116 bool popup_move_textbox_dlg(string const& msg, char* textbox, char const* title)
6117 {
6118 char buf1[512] = {0};
6119 char buf2[512] = {0};
6120 large_dialog(move_textbox_list_dlg);
6121 DIALOG& tbox = move_textbox_list_dlg[3];
6122 {
6123 FONT* f = tbox.dp2 ? (FONT*)tbox.dp2 : get_custom_font(CFONT_GUI);
6124 int indx = 0, word_indx = 0;
6125 for(char c : msg)
6126 {
6127 if(c == ' ' || c == '\n')
6128 word_indx = indx;
6129 buf1[indx++] = c;
6130 if(c == '\n' || text_length(f, buf1) >= tbox.w)
6131 {
6132 buf1[word_indx] = 0;
6133 strcpy(buf2, msg.c_str()+word_indx+1);
6134 break;
6135 }
6136 }
6137 }
6138
6139 move_textbox_list_dlg[0].dp = (void*)title;
6140 move_textbox_list_dlg[0].dp2 = get_zc_font(font_lfont);
6141 move_textbox_list_dlg[1].dp = buf1;
6142 move_textbox_list_dlg[2].dp = buf2;
6143 tbox.dp = textbox;
6144 tbox.d2 = 0;
6145 auto tby = tbox.y;
6146 auto tbh = tbox.h;
6147 if(!buf2[0])
6148 {
6149 auto diff = move_textbox_list_dlg[2].h;
6150 tbox.y -= diff;
6151 tbox.h += diff;
6152 }
6153
6154 int32_t ret=do_zqdialog(move_textbox_list_dlg,2);
6155 position_mouse_z(0);
6156 tbox.y = tby;
6157 tbox.h = tbh;
6158
6159 return ret == 4;
6160 }
6161
6162 int32_t quick_select_3(int32_t a, int32_t b, int32_t c, int32_t d)
6163 {
6164 return a==0?b:a==1?c:d;
6165 }
6166
6167 bool TileMoveList::process(std::unique_ptr<BaseTileRef>& ref, TileMoveProcess const& proc, bool is_dest)
6168 {
6169 TileRefCombo* combo_ref = dynamic_cast<TileRefCombo*>(ref.get());
6170 int i = ti_none;
6171 auto t = ref->getTile() + ref->offset();
6172
6173 if(combo_ref)
6174 {
6175 if(proc.rect)
6176 i=move_intersection_sr(*combo_ref->combo, proc._l, proc._t, proc._w, proc._h);
6177 else i=move_intersection_ss(*combo_ref->combo, proc._first, proc._last);
6178 }
6179 else if(proc.rect)
6180 {
6181 if(ref->h > 1)
6182 i=move_intersection_rr(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._l, proc._t, proc._w, proc._h);
6183 else i=move_intersection_sr(t, t+ref->w-1, proc._l, proc._t, proc._w, proc._h);
6184 }
6185 else
6186 {
6187 if(ref->h > 1)
6188 i=move_intersection_rs(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._first, proc._last);
6189 else i=move_intersection_ss(t, t+ref->w-1, proc._first, proc._last);
6190 }
6191
6192 bool in = i != ti_none, out = i != ti_encompass;
6193 for(size_t q = 0; !(in&&out) && q < ref->extra_rects.size(); ++q)
6194 {
6195 auto [ex_t,ex_w,ex_h] = ref->extra_rects[q];
6196 if(proc.rect)
6197 i = move_intersection_rr(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._l, proc._t, proc._w, proc._h);
6198 else i = move_intersection_rs(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._first, proc._last);
6199 if(i != ti_none)
6200 in = true;
6201 if(i != ti_encompass)
6202 out = true;
6203 }
6204 i = in ? (out ? ti_broken : ti_encompass) : ti_none;
6205
6206 if(i != ti_none && ref->getTile() != 0)
6207 {
6208 if(mode == Mode::CHECK_ALL)
6209 {
6210 move_refs.emplace_back(std::move(ref));
6211 return true;
6212 }
6213 else if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6214 {
6215 if(warning_flood || warning_list.tellp() >= 65000)
6216 {
6217 if(!warning_flood)
6218 warning_list << "...\n...\n...\nmany others";
6219 warning_flood = true;
6220 }
6221 else
6222 warning_list << ref->name << '\n';
6223 }
6224 else if(i==ti_encompass)
6225 {
6226 move_refs.emplace_back(std::move(ref));
6227 return true;
6228 }
6229 }
6230 return false;
6231 }
6232
6233 bool TileMoveList::check_prot()
6234 {
6235 if(!TileProtection)
6236 return true;
6237 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Tile Warning");
6238
6239 warning_flood = false;
6240 warning_list.clear();
6241
6242 return ret;
6243 }
6244
6245 void TileMoveList::add_diff(int diff)
6246 {
6247 for(auto& ref : move_refs)
6248 ref->addTile(diff);
6249 }
6250
6251 //from 'combo.h'
6252 bool ComboMoveList::process(std::unique_ptr<BaseComboRef>& ref, ComboMoveProcess const& proc, bool is_dest)
6253 {
6254 int i = ti_none;
6255 auto c = ref->getCombo();
6256
6257 if(ref->no_move)
6258 processed_combos[c] = true;
6259 else processed_combos[c]; //inserts element if does not exist
6260 i = move_intersection_ss(c, c, proc._first, proc._last);
6261
6262 if(i != ti_none && ref->getCombo() != 0)
6263 {
6264 if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6265 {
6266 if(ComboProtection)
6267 {
6268 if(warning_flood || warning_list.tellp() >= 65000)
6269 {
6270 if(!warning_flood)
6271 warning_list << "...\n...\n...\nmany others";
6272 warning_flood = true;
6273 }
6274 else
6275 warning_list << ref->name << '\n';
6276 }
6277 }
6278 else if(i==ti_encompass)
6279 {
6280 move_refs.emplace_back(std::move(ref));
6281 return true;
6282 }
6283 }
6284 return false;
6285 }
6286
6287 bool ComboMoveList::check_prot()
6288 {
6289 if(!ComboProtection)
6290 return true;
6291 vector<set<int> const*> subset = combo_links.subset(processed_combos);
6292 bool subset_header = false;
6293 for(int q = 0; q < 2; ++q)
6294 {
6295 bool is_dest = (q==1);
6296 if(!is_dest && !source_process)
6297 continue;
6298 ComboMoveProcess const& proc = is_dest ? dest_process : *source_process;
6299 for(auto it = subset.begin(); it != subset.end();)
6300 {
6301 auto s = *it;
6302 if(warning_flood || warning_list.tellp() >= 65000)
6303 {
6304 if(!warning_flood)
6305 warning_list << "...\n...\n...\nmany others";
6306 warning_flood = true;
6307 break;
6308 }
6309 set<int> in_set, out_set;
6310 bool no_move = is_dest;
6311 for(int c : *s)
6312 {
6313 int i = move_intersection_ss(c, c, proc._first, proc._last);
6314 if(i != ti_none)
6315 in_set.insert(c);
6316 if(i != ti_encompass)
6317 out_set.insert(c);
6318 if(!no_move)
6319 {
6320 auto it = processed_combos.find(c);
6321 if(it != processed_combos.end() && it->second)
6322 no_move = true;
6323 }
6324 }
6325 int i = in_set.empty() ? ti_none : (out_set.empty() ? ti_encompass : ti_broken);
6326 if(i == ti_encompass && !no_move)
6327 {
6328 it = subset.erase(it);
6329 continue;
6330 }
6331 if(i == ti_none)
6332 {
6333 ++it;
6334 continue;
6335 }
6336
6337 if(!subset_header)
6338 {
6339 subset_header = true;
6340 warning_list << "===== Broken Relative Combo Groups =====\n";
6341 }
6342 bool comma = false;
6343 warning_list << "In(";
6344 for(int c : in_set)
6345 {
6346 if(comma)
6347 warning_list << ",";
6348 else comma = true;
6349 warning_list << c;
6350 }
6351 warning_list << "),Out(";
6352 comma = false;
6353 for(int c : out_set)
6354 {
6355 if(comma)
6356 warning_list << ",";
6357 else comma = true;
6358 warning_list << c;
6359 }
6360 warning_list << ")\n";
6361 it = subset.erase(it);
6362 }
6363 }
6364 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Combo Warning");
6365
6366 processed_combos.clear();
6367 warning_flood = false;
6368 warning_list.clear();
6369
6370 return ret;
6371 }
6372
6373 void ComboMoveList::add_diff(int diff)
6374 {
6375 for(auto& ref : move_refs)
6376 ref->addCombo(diff);
6377 }
6378
6379 static void collect_subscreen_tiles(SubscrWidget& widget, TileMoveList& list)
6380 {
6381 if (auto w = dynamic_cast<SW_2x2Frame*>(&widget))
6382 {
6383 list.add_tile(&w->tile, 2, 2, "2x2 Frame");
6384 }
6385 else if (auto w = dynamic_cast<SW_TriFrame*>(&widget))
6386 {
6387 list.add_tile(&w->frame_tile, 6, 3, "McGuffin Frame - Frame");
6388 list.add_tile(&w->piece_tile, "McGuffin Frame - Piece");
6389 }
6390 else if (auto w = dynamic_cast<SW_McGuffin*>(&widget))
6391 {
6392 list.add_tile(&w->tile, "McGuffin Piece");
6393 }
6394 else if (auto w = dynamic_cast<SW_TileBlock*>(&widget))
6395 {
6396 list.add_tile(&w->tile, w->w, w->h, "TileBlock");
6397 }
6398 else if (auto w = dynamic_cast<SW_MiniTile*>(&widget))
6399 {
6400 if (w->tile == -1)
6401 return;
6402
6403 list.add_tile(&w->tile, "MiniTile");
6404 }
6405 else if (auto w = dynamic_cast<SW_GaugePiece*>(&widget))
6406 {
6407 int fr = w->frames ? w->frames : 1;
6408 fr = fr * (1+(w->get_per_container()/(w->unit_per_frame+1)));
6409 if(!(w->flags&SUBSCR_GAUGE_FULLTILE))
6410 fr = (fr/4_zf).getCeil();
6411
6412 for(auto q = 0; q < 4; ++q)
6413 {
6414 list.add_tile(&w->mts[q].mt_tile, fr, 1, fmt::format("Gauge Tile {}", q));
6415 }
6416 }
6417 }
6418
6419 static void collect_subscreen_tiles(SubscrPage& page, TileMoveList& list)
6420 {
6421 for(auto q = 0; q < page.contents.size(); ++q)
6422 {
6423 size_t indx = list.move_refs.size();
6424 collect_subscreen_tiles(*page.contents[q], list);
6425 for(; indx < list.move_refs.size(); ++indx)
6426 {
6427 auto& ref = list.move_refs[indx];
6428 ref->name = fmt::format("Widget {} - {}", q, ref->name);
6429 }
6430 }
6431 }
6432
6433 static void collect_subscreen_tiles(ZCSubscreen& subscreen, TileMoveList& list)
6434 {
6435 for (auto q = 0; q < subscreen.pages.size(); ++q)
6436 {
6437 size_t indx = list.move_refs.size();
6438 collect_subscreen_tiles(subscreen.pages[q], list);
6439 for(; indx < list.move_refs.size(); ++indx)
6440 {
6441 auto& ref = list.move_refs[indx];
6442 ref->name = fmt::format("Page {} - {}", q, ref->name);
6443 }
6444 }
6445 }
6446
6447 bool _handle_tile_move(TileMoveProcess dest_process, optional<TileMoveProcess> source_process, int diff, TileMoveUndo* on_undo = nullptr, std::function<void(int32_t)> every_proc = nullptr, TileMoveList::Mode mode = TileMoveList::Mode::MOVE)
6448 {
6449 bool BSZ2 = get_qr(qr_BSZELDA);
6450 bool move = source_process.has_value();
6451 TileMoveUndo local_undo;
6452 TileMoveUndo& storage = on_undo ? *on_undo : local_undo;
6453 auto& vec = storage.vec;
6454 storage.diff = diff;
6455 storage.state = false;
6456
6457 //Combos
6458 {
6459 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6460 dest_process, source_process, mode,
6461 move
6462 ? "The tiles used by the following combos will be partially cleared by the move."
6463 : "The tiles used by the following combos will be partially or completely overwritten by this process."
6464 ));
6465 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6466 {
6467 auto& cmb = combobuf[q];
6468 auto lbl = fmt::format("Combo {}{}", q, cmb.label.empty() ? ""
6469 : fmt::format(" ({})", cmb.label));
6470 movelist->add_combo(&cmb, lbl);
6471
6472 //type-specific
6473 char const* type_name = ZI.getComboTypeName(cmb.type);
6474 switch(cmb.type)
6475 {
6476 case cSPOTLIGHT:
6477 {
6478 if(!(cmb.usrflags & cflag1))
6479 break;
6480 movelist->add_tile_10k(&cmb.attributes[0], 16, 1, fmt::format("{} - Type '{}' - Beam Tiles", lbl, type_name));
6481 break;
6482 }
6483 }
6484 }
6485 if(!every_proc && !movelist->check_prot())
6486 return false;
6487 }
6488 //Items
6489 {
6490 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6491 dest_process, source_process, mode,
6492 move
6493 ? "The tiles used by the following items will be partially cleared by the move."
6494 : "The tiles used by the following items will be partially or completely overwritten by this process."
6495 ));
6496 build_bii_list(false);
6497 for(int32_t u=0; u<MAXITEMS; u++)
6498 {
6499 auto id = bii[u].i;
6500 itemdata& itm = itemsbuf[id];
6501 if(itm.family == itype_bottle)
6502 {
6503 vector<std::tuple<int,int,int>> rects;
6504 auto fr = itm.frames;
6505 for(int q = 0; q < NUM_BOTTLE_TYPES; ++q)
6506 {
6507 bottletype const& bt = QMisc.bottle_types[q];
6508 if(bt.is_blank())
6509 continue;
6510 rects.emplace_back(fr+q*fr, fr, 1);
6511 }
6512 movelist->add_tile(&itm.tile, fr, 1, fmt::format("Item {}", id),
6513 false, 0, 0, rects);
6514 }
6515 else movelist->add_tile(&itm.tile, itm.frames, 1, fmt::format("Item {}", id));
6516 }
6517 if(!every_proc && !movelist->check_prot())
6518 return false;
6519 }
6520 //Weapon sprites
6521 {
6522 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6523 dest_process, source_process, mode,
6524 move
6525 ? "The tiles used by the following weapons will be partially cleared by the move."
6526 : "The tiles used by the following weapons will be partially or completely overwritten by this process."
6527 ));
6528 build_biw_list();
6529
6530 for(int32_t u=0; u<MAXWPNS; u++)
6531 {
6532 bool ignore_frames=false;
6533 int32_t m=0;
6534
6535 auto id = biw[u].i;
6536 auto& wpn = wpnsbuf[id];
6537
6538 switch(biw[u].i)
6539 {
6540 case wSWORD:
6541 case wWSWORD:
6542 case wMSWORD:
6543 case wXSWORD:
6544 m=3+((wpnsbuf[biw[u].i].type==3)?1:0);
6545 break;
6546
6547 case wSWORDSLASH:
6548 case wWSWORDSLASH:
6549 case wMSWORDSLASH:
6550 case wXSWORDSLASH:
6551 m=4;
6552 break;
6553
6554 case iwMMeter:
6555 m=9;
6556 break;
6557
6558 case wBRANG:
6559 case wMBRANG:
6560 case wFBRANG:
6561 m=BSZ2?1:3;
6562 break;
6563
6564 case wBOOM:
6565 case wSBOOM:
6566 case ewBOOM:
6567 case ewSBOOM:
6568 ignore_frames=true;
6569 m=2;
6570 break;
6571
6572 case wWAND:
6573 m=1;
6574 break;
6575
6576 case wMAGIC:
6577 m=1;
6578 break;
6579
6580 case wARROW:
6581 case wSARROW:
6582 case wGARROW:
6583 case ewARROW:
6584 m=1;
6585 break;
6586
6587 case wHAMMER:
6588 m=8;
6589 break;
6590
6591 case wHSHEAD:
6592 m=1;
6593 break;
6594
6595 case wHSCHAIN_H:
6596 m=1;
6597 break;
6598
6599 case wHSCHAIN_V:
6600 m=1;
6601 break;
6602
6603 case wHSHANDLE:
6604 m=1;
6605 break;
6606
6607 case iwDeath:
6608 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6609 {
6610 ignore_frames = true;
6611 m=BSZ2?4:2;
6612 }
6613 break;
6614
6615 case iwSpawn:
6616 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6617 {
6618 ignore_frames = true;
6619 m=3;
6620 }
6621 break;
6622 }
6623
6624 movelist->add_tile(&wpn.tile, zc_max((ignore_frames?0:wpn.frames),1)+m,
6625 1, fmt::format("{} {}", biw[u].s, id));
6626
6627 //Tile 54+55 are "Impact (not shown in sprite list)", for u==3 "Arrow" and u==9 "Boomerang"
6628 //...these can't be updated by a move.
6629 if((u==3)||(u==9))
6630 {
6631 static int32_t impact_tiles[2] = {54,54};
6632 auto& tile = impact_tiles[u==3 ? 0 : 1];
6633 tile = 54; //dummy tile, ensure it's correct
6634 movelist->add_tile(&tile, 2, 1,
6635 fmt::format("{} Impact (not shown in sprite list)",(u==3)?"Arrow":"Boomerang"),
6636 true);
6637 }
6638 }
6639 if(!every_proc && !movelist->check_prot())
6640 return false;
6641 }
6642 //Hero sprites
6643 {
6644 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6645 dest_process, source_process, mode,
6646 move
6647 ? "The tiles used by the following Hero sprites will be partially cleared by the move."
6648 : "The tiles used by the following Hero sprites will be partially or completely overwritten by this process."
6649 ));
6650 {
6651 int32_t a_style=(zinit.heroAnimationStyle);
6652 #define ADD_HERO_SPRITE(ref_sprite, frames, name) \
6653 do \
6654 { \
6655 movelist->add_tile(&ref_sprite[spr_tile], \
6656 (ref_sprite[spr_extend] < 2 ? 1 : 2) * frames, \
6657 ref_sprite[spr_extend] < 1 ? 1 : 2, \
6658 name, false, \
6659 ref_sprite[spr_extend] < 2 ? 0 : -1, \
6660 ref_sprite[spr_extend] < 1 ? 0 : -1); \
6661 } while(false)
6662 // + (ref_sprite[spr_extend] < 2 ? 0 : 1) //this was on some of the 'width's before... but doesn't make sense?
6663
6664 for(int32_t i=0; i<4; ++i)
6665 {
6666 ADD_HERO_SPRITE(walkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Walking ({})", dirstr_proper[i]));
6667 }
6668
6669 for(int32_t i=0; i<4; ++i)
6670 {
6671 ADD_HERO_SPRITE(slashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slashing ({})", dirstr_proper[i]));
6672 }
6673
6674 for(int32_t i=0; i<4; ++i)
6675 {
6676 ADD_HERO_SPRITE(stabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Stabbing ({})", dirstr_proper[i]));
6677 }
6678
6679 for(int32_t i=0; i<4; ++i)
6680 {
6681 ADD_HERO_SPRITE(poundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Pounding ({})", dirstr_proper[i]));
6682 }
6683
6684 for(int32_t i=0; i<2; ++i)
6685 {
6686 ADD_HERO_SPRITE(holdspr[0][i], 1, fmt::format("Hold (Land, {}-hand)", i+1));
6687 }
6688
6689 ADD_HERO_SPRITE(castingspr, 1, "Casting");
6690
6691 for(int32_t i=0; i<4; ++i)
6692 {
6693 ADD_HERO_SPRITE(floatspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Floating ({})", dirstr_proper[i]));
6694 }
6695
6696 for(int32_t i=0; i<4; ++i)
6697 {
6698 ADD_HERO_SPRITE(swimspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Swimming ({})", dirstr_proper[i]));
6699 }
6700
6701 for(int32_t i=0; i<4; ++i)
6702 {
6703 ADD_HERO_SPRITE(divespr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Diving ({})", dirstr_proper[i]));
6704 }
6705
6706 for(int32_t i=0; i<2; ++i)
6707 {
6708 ADD_HERO_SPRITE(holdspr[1][i], 1, fmt::format("Hold (Water, {}-hand)", i));
6709 }
6710
6711 for(int32_t i=0; i<4; ++i)
6712 {
6713 ADD_HERO_SPRITE(jumpspr[i], 3, fmt::format("Jumping ({})", dirstr_proper[i]));
6714 }
6715
6716 for(int32_t i=0; i<4; ++i)
6717 {
6718 ADD_HERO_SPRITE(chargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Charging ({})", dirstr_proper[i]));
6719 }
6720 for(int32_t i=0; i<4; ++i)
6721 {
6722 ADD_HERO_SPRITE(revslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slash 2 ({})", dirstr_proper[i]));
6723 }
6724 for(int32_t i=0; i<4; ++i)
6725 {
6726 ADD_HERO_SPRITE(fallingspr[i], 7, fmt::format("Falling ({})", dirstr_proper[i]));
6727 }
6728 for(int32_t i=0; i<4; ++i)
6729 {
6730 ADD_HERO_SPRITE(liftingspr[i], liftingspr[i][spr_frames], fmt::format("Lifting ({})", dirstr_proper[i]));
6731 }
6732 for(int32_t i=0; i<4; ++i)
6733 {
6734 ADD_HERO_SPRITE(liftingwalkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Lift-Walking ({})", dirstr_proper[i]));
6735 }
6736 for(int32_t i=0; i<4; ++i)
6737 {
6738 ADD_HERO_SPRITE(drowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Drowning ({})", dirstr_proper[i]));
6739 }
6740 for(int32_t i=0; i<4; ++i)
6741 {
6742 ADD_HERO_SPRITE(drowning_lavaspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Lava Drowning ({})", dirstr_proper[i]));
6743 }
6744 for(int32_t i=0; i<4; ++i)
6745 {
6746 ADD_HERO_SPRITE(sideswimspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swimming ({})", dirstr_proper[i]));
6747 }
6748 //69
6749 for(int32_t i=0; i<4; ++i)
6750 {
6751 ADD_HERO_SPRITE(sideswimslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Side-Swim Slash ({})", dirstr_proper[i]));
6752 }
6753 //73
6754 for(int32_t i=0; i<4; ++i)
6755 {
6756 ADD_HERO_SPRITE(sideswimstabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Stab ({})", dirstr_proper[i]));
6757 }
6758 //77
6759 for(int32_t i=0; i<4; ++i)
6760 {
6761 ADD_HERO_SPRITE(sideswimpoundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Pound ({})", dirstr_proper[i]));
6762 }
6763 //81
6764 for(int32_t i=0; i<4; ++i)
6765 {
6766 ADD_HERO_SPRITE(sideswimchargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Side-Swim Charging ({})", dirstr_proper[i]));
6767 }
6768 //85
6769 ADD_HERO_SPRITE(sideswimholdspr[spr_hold1], 1, "Hold (Side-Water, 1-hand)");
6770 ADD_HERO_SPRITE(sideswimholdspr[spr_hold2], 1, "Hold (Side-Water, 2-hand)");
6771 ADD_HERO_SPRITE(sideswimcastingspr, 1, "Side-Swim Casting");
6772 for(int32_t i=0; i<4; ++i)
6773 {
6774 ADD_HERO_SPRITE(sidedrowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swim Drowning ({})", dirstr_proper[i]));
6775 }
6776 //91
6777 }
6778 if(!every_proc && !movelist->check_prot())
6779 return false;
6780 }
6781 //Map Styles
6782 {
6783 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6784 dest_process, source_process, mode,
6785 move
6786 ? "The tiles used by the following map styles will be partially cleared by the move."
6787 : "The tiles used by the following map styles will be partially or completely overwritten by this process."
6788 ));
6789 movelist->add_tile(&QMisc.colors.blueframe_tile, 2, 2, "Frame");
6790 movelist->add_tile(&QMisc.colors.HCpieces_tile, zinit.hcp_per_hc, 1, "Heart Container Piece");
6791 movelist->add_tile(&QMisc.colors.triforce_tile, BSZ2?2:1, BSZ2?3:1, "McGuffin Fragment");
6792 movelist->add_tile(&QMisc.colors.triframe_tile, BSZ2?7:6, BSZ2?7:3, "McGuffin Frame");
6793 movelist->add_tile(&QMisc.colors.overworld_map_tile, 5, 3, "Overworld Map");
6794 movelist->add_tile(&QMisc.colors.dungeon_map_tile, 5, 3, "Dungeon Map");
6795 if(!every_proc && !movelist->check_prot())
6796 return false;
6797 }
6798 //Game Icons
6799 {
6800 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6801 dest_process, source_process, mode,
6802 move
6803 ? "The tiles used by the following game icons will be partially cleared by the move."
6804 : "The tiles used by the following game icons will be partially or completely overwritten by this process."
6805 ));
6806 for(int32_t u=0; u<4; u++)
6807 movelist->add_tile(&QMisc.icons[u], fmt::format("Game Icon {}", u));
6808 if(!every_proc && !movelist->check_prot())
6809 return false;
6810 }
6811 //DMaps
6812 {
6813 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6814 dest_process, source_process, mode,
6815 move
6816 ? "The tiles used by the following dmaps will be partially cleared by the move."
6817 : "The tiles used by the following dmaps will be partially or completely overwritten by this process."
6818 ));
6819 for(int32_t u=0; u<MAXDMAPS; u++)
6820 {
6821 auto& dm = DMaps[u];
6822 movelist->add_tile(&dm.minimap_1_tile, 5, 3, fmt::format("DMap {} - Minimap (Empty)", u));
6823 movelist->add_tile(&dm.minimap_2_tile, 5, 3, fmt::format("DMap {} - Minimap (Filled)", u));
6824 movelist->add_tile(&dm.largemap_1_tile, BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Empty)", u));
6825 movelist->add_tile(&dm.largemap_2_tile, BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Filled)", u));
6826 }
6827 if(!every_proc && !movelist->check_prot())
6828 return false;
6829 }
6830 //Enemies
6831 {
6832 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6833 dest_process, source_process, mode,
6834 move
6835 ? "The tiles used by the following enemies will be partially cleared by the move."
6836 : "The tiles used by the following enemies will be partially or completely overwritten by this process."
6837 ));
6838 build_bie_list(false);
6839 bool newtiles=get_qr(qr_NEWENEMYTILES)!=0;
6840 for(int u=0; u<eMAXGUYS; u++)
6841 {
6842 guydata& enemy=guysbuf[bie[u].i];
6843 bool darknut=false;
6844 bool gleeok=false;
6845
6846 if(enemy.family==eeWALK && ((enemy.flags&(guy_shield_back|guy_shield_front|guy_shield_left|guy_shield_right))!=0))
6847 darknut=true;
6848 else if(enemy.family==eeGLEEOK)
6849 gleeok=true;
6850 else if (enemy.family == eePATRA)
6851 {
6852 if (!get_qr(qr_PATRAS_USE_HARDCODED_OFFSETS))
6853 {
6854 darknut=true; //uses the same logic no need for separate variables!
6855 }
6856 }
6857
6858 // Dummied out enemies
6859 if(bie[u].i>=eOCTO1S && bie[u].i<e177)
6860 {
6861 if(old_guy_string[bie[u].i][strlen(old_guy_string[bie[u].i])-1]==' ')
6862 {
6863 continue;
6864 }
6865 }
6866
6867 if(newtiles)
6868 {
6869 if(enemy.e_tile==0)
6870 {
6871 continue;
6872 }
6873
6874 vector<std::tuple<int,int,int>> rects;
6875
6876 if(darknut) //or anything that uses S. Tile for with new tiles
6877 {
6878 if (enemy.s_tile != 0)
6879 {
6880 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6881 }
6882 }
6883 else if (gleeok)
6884 {
6885 for (int32_t j = 0; j < enemy.attributes[4]; ++j)
6886 {
6887 rects.emplace_back(enemy.attributes[5] + (enemy.attributes[6]*j), 4, 1);
6888 }
6889 rects.emplace_back(enemy.attributes[7], 4, 1);
6890 rects.emplace_back(enemy.attributes[8], 4, 1);
6891 }
6892 movelist->add_tile(&enemy.e_tile, enemy.e_width, enemy.e_height, fmt::format("Enemy {} ({}) 'New'", u, bie[u].s),
6893 false, 0, 0, rects);
6894
6895 }
6896 else
6897 {
6898 if(enemy.tile==0)
6899 {
6900 continue;
6901 }
6902 movelist->add_tile(&enemy.tile, enemy.width, enemy.height, fmt::format("Enemy {} ({}) 'Old'", u, bie[u].s));
6903
6904 if(enemy.s_tile!=0)
6905 {
6906 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6907 }
6908 }
6909 }
6910 if(!every_proc && !movelist->check_prot())
6911 return false;
6912 }
6913 //Subscreens
6914 {
6915 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6916 dest_process, source_process, mode,
6917 move
6918 ? "The tiles used by the following subscreen widgets will be partially cleared by the move."
6919 : "The tiles used by the following subscreen widgets will be partially or completely overwritten by this process."
6920 ));
6921
6922 for(auto q = 0; q < subscreens_active.size(); ++q)
6923 {
6924 size_t indx = movelist->move_refs.size();
6925 collect_subscreen_tiles(subscreens_active[q], *movelist.get());
6926 for(; indx < movelist->move_refs.size(); ++indx)
6927 {
6928 auto& ref = movelist->move_refs[indx];
6929 ref->name = fmt::format("Active Subscr {} - {}", q, ref->name);
6930 }
6931 }
6932 for(auto q = 0; q < subscreens_passive.size(); ++q)
6933 {
6934 size_t indx = movelist->move_refs.size();
6935 collect_subscreen_tiles(subscreens_passive[q], *movelist.get());
6936 for(; indx < movelist->move_refs.size(); ++indx)
6937 {
6938 auto& ref = movelist->move_refs[indx];
6939 ref->name = fmt::format("Passive Subscr {} - {}", q, ref->name);
6940 }
6941 }
6942 for(auto q = 0; q < subscreens_overlay.size(); ++q)
6943 {
6944 size_t indx = movelist->move_refs.size();
6945 collect_subscreen_tiles(subscreens_overlay[q], *movelist.get());
6946 for(; indx < movelist->move_refs.size(); ++indx)
6947 {
6948 auto& ref = movelist->move_refs[indx];
6949 ref->name = fmt::format("Overlay Subscr {} - {}", q, ref->name);
6950 }
6951 }
6952 if(!every_proc && !movelist->check_prot())
6953 return false;
6954 }
6955 //Strings
6956 {
6957 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6958 dest_process, source_process, mode,
6959 move
6960 ? "The tiles used by the following strings will be partially cleared by the move."
6961 : "The tiles used by the following strings will be partially or completely overwritten by this process."
6962 ));
6963 for(size_t q = 0; q < msg_count; ++q)
6964 {
6965 MsgStr& str = MsgStrings[q];
6966 std::string text = str.serialize();
6967 bool fulltile = str.stringflags & STRINGFLAG_FULLTILE;
6968 movelist->add_tile(&str.tile, fulltile ? (str.w/16_zf).getCeil() : 2,
6969 fulltile ? (str.h/16_zf).getCeil() : 2, fmt::format("{} (BG): '{}'", q, util::snip(text,100)));
6970 movelist->add_tile(&str.portrait_tile, str.portrait_tw, str.portrait_th,
6971 fmt::format("{} (Port.): '{}'", q, util::snip(text,100)));
6972 }
6973 if(!every_proc && !movelist->check_prot())
6974 return false;
6975 }
6976
6977 if(source_process) //Apply the 'diff' value to all moved tiles
6978 storage.redo();
6979 if(every_proc)
6980 for(auto &list : vec)
6981 for(auto &ref : list->move_refs)
6982 ref->forEach(every_proc);
6983 return true;
6984 }
6985 bool handle_tile_move(TileMoveProcess dest_process)
6986 {
6987 return _handle_tile_move(dest_process, nullopt, 0);
6988 }
6989 bool handle_tile_move(TileMoveProcess dest_process, TileMoveProcess source_process, int diff, TileMoveUndo& on_undo)
6990 {
6991 return _handle_tile_move(dest_process, source_process, diff, &on_undo);
6992 }
6993 void for_every_used_tile(std::function<void(int32_t)> proc)
6994 {
6995 reset_combo_animations();
6996 reset_combo_animations2();
6997 TileMoveProcess all_tiles {.rect = false, ._first = 0, ._last = NEWMAXTILES-1};
6998 _handle_tile_move(all_tiles, nullopt, 0, nullptr, proc, TileMoveList::Mode::CHECK_ALL);
6999 }
7000
7001 bool _handle_combo_move(ComboMoveProcess dest_process, optional<ComboMoveProcess> source_process, int diff, ComboMoveUndo* on_undo)
7002 {
7003 bool BSZ2 = get_qr(qr_BSZELDA);
7004 bool move = source_process.has_value();
7005 ComboMoveUndo local_undo;
7006 ComboMoveUndo& storage = on_undo ? *on_undo : local_undo;
7007 auto& vec = storage.vec;
7008 auto& combo_links = storage.combo_links;
7009 storage.diff = diff;
7010 storage.state = false;
7011 //Combo relative links
7012 {
7013 for(int32_t q = 0; q < MAXCOMBOS; ++q)
7014 {
7015 newcombo& cmb = combobuf[q];
7016 if(cmb.trigchange)
7017 combo_links.add_to(q, q+cmb.trigchange);
7018 bool next = cmb.flag == mfSECRETSNEXT;
7019 switch(cmb.type)
7020 {
7021 case cPOUND:
7022 case cLOCKBLOCK: case cLOCKBLOCK2:
7023 case cBOSSLOCKBLOCK: case cBOSSLOCKBLOCK2:
7024 case cCHEST: case cCHEST2:
7025 case cLOCKEDCHEST: case cLOCKEDCHEST2:
7026 case cBOSSCHEST: case cBOSSCHEST2:
7027 case cSTEP: case cSTEPSAME: case cSTEPALL: case cSTEPCOPY:
7028 case cSLASHNEXT: case cSLASHNEXTITEM: case cBUSHNEXT:
7029 case cSLASHNEXTTOUCHY: case cSLASHNEXTITEMTOUCHY: case cBUSHNEXTTOUCHY:
7030 case cTALLGRASSNEXT: case cCRUMBLE:
7031 next = true;
7032 break;
7033 case cCSWITCH: case cCSWITCHBLOCK:
7034 combo_links.add_to(q, q+cmb.attributes[0]);
7035 break;
7036 case cLIGHTTARGET:
7037 if(cmb.usrflags & cflag1)
7038 combo_links.add_to(q, q-1);
7039 else next = true;
7040 break;
7041 case cSTEPSFX:
7042 if((cmb.usrflags&(cflag1|cflag3)) == cflag1)
7043 next = true;
7044 break;
7045 }
7046 if(next)
7047 combo_links.add_to(q, q+1);
7048 }
7049 }
7050
7051 //This function is expensive! Any optimizations possible should be made. -Em
7052
7053 //OPT: Check for a 0-val preemptively, to avoid processing the fmt::format strings
7054 #define ADDC(ptr, str) \
7055 if(*ptr) movelist->add_combo(ptr, ComboProtection ? str : "");
7056 #define ADDC_10k(ptr, str) \
7057 if(*ptr) movelist->add_combo_10k(ptr, ComboProtection ? str : "");
7058 //Combos
7059 {
7060 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7061 combo_links, dest_process, source_process,
7062 move
7063 ? "The combos used by the following combos will be partially cleared by the move."
7064 : "The combos used by the following combos will be partially or completely overwritten by this process."
7065 ));
7066 for(int32_t q = 0; q < MAXCOMBOS; ++q)
7067 {
7068 newcombo& cmb = combobuf[q];
7069 auto lbl = fmt::format("{}{}", q, cmb.label.empty() ? ""
7070 : fmt::format(" ({})", cmb.label));
7071 ADDC(&cmb.nextcombo, fmt::format("{} - Combo Cycle", lbl));
7072 ADDC(&cmb.liftcmb, fmt::format("{} - Lift Combo", lbl));
7073 ADDC(&cmb.liftundercmb, fmt::format("{} - Lift Undercombo", lbl));
7074 ADDC(&cmb.prompt_cid, fmt::format("{} - Triggers ButtonPrompt", lbl));
7075
7076 //type-specific
7077 char const* type_name = ZI.getComboTypeName(cmb.type);
7078 switch(cmb.type)
7079 {
7080 case cLOCKEDCHEST: case cBOSSCHEST:
7081 if(cmb.usrflags & cflag13)
7082 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7083 [[fallthrough]];
7084 case cCHEST:
7085 if(cmb.usrflags & cflag13)
7086 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7087 break;
7088 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
7089 if(cmb.usrflags & cflag13)
7090 {
7091 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7092 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7093 }
7094 break;
7095 case cSIGNPOST:
7096 if(cmb.usrflags & cflag13)
7097 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7098 break;
7099 case cBUTTONPROMPT:
7100 if(cmb.usrflags & cflag13)
7101 ADDC_10k(&cmb.attributes[0], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7102 break;
7103 }
7104 }
7105
7106 if(!movelist->check_prot())
7107 return false;
7108 }
7109 //Door Combo Sets
7110 {
7111 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7112 combo_links, dest_process, source_process,
7113 move
7114 ? "The combos used by the following screens will be partially cleared by the move."
7115 : "The combos used by the following screens will be partially or completely overwritten by this process."
7116 ));
7117 static const char* door_names[9] = {
7118 "Wall", "Locked", "Shuttered", "Boss", "Bombed", "Open", "Unlocked", "Open Shuttered", "Open Boss"
7119 };
7120 for(int32_t i=0; i<MAXDOORCOMBOSETS; i++)
7121 {
7122 auto& dcs = DoorComboSets[i];
7123 auto& name = DoorComboSetNames[i];
7124 for(int32_t j=0; j<9; j++)
7125 {
7126 if(j<4)
7127 {
7128 ADDC(&dcs.walkthroughcombo[j], fmt::format("{} ({}): Walk-Through {}", i, name, j));
7129
7130 if(j<3)
7131 {
7132 if(j<2)
7133 {
7134 ADDC(&dcs.bombdoorcombo_u[j], fmt::format("{} ({}): Unused? bombdoorcombo_u {}", i, name, j));
7135 ADDC(&dcs.bombdoorcombo_d[j], fmt::format("{} ({}): Unused? bombdoorcombo_d {}", i, name, j));
7136 }
7137 ADDC(&dcs.bombdoorcombo_l[j], fmt::format("{} ({}): Unused? bombdoorcombo_l {}", i, name, j));
7138 ADDC(&dcs.bombdoorcombo_r[j], fmt::format("{} ({}): Unused? bombdoorcombo_r {}", i, name, j));
7139 }
7140 }
7141
7142 for(int32_t k=0; k<6; k++)
7143 {
7144 if(k<4)
7145 {
7146 ADDC(&dcs.doorcombo_u[j][k], fmt::format("{} ({}): Top, {} #{}", i, name, door_names[j], k));
7147 ADDC(&dcs.doorcombo_d[j][k], fmt::format("{} ({}): Bottom, {} #{}", i, name, door_names[j], k));
7148 }
7149
7150 ADDC(&dcs.doorcombo_l[j][k], fmt::format("{} ({}): Left, {} #{}", i, name, door_names[j], k));
7151 ADDC(&dcs.doorcombo_r[j][k], fmt::format("{} ({}): Right, {} #{}", i, name, door_names[j], k));
7152 }
7153 }
7154 }
7155
7156 if(!movelist->check_prot())
7157 return false;
7158 }
7159 //Combo Pools
7160 {
7161 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7162 combo_links, dest_process, source_process,
7163 move
7164 ? "The combos used by the following combo pools will be partially cleared by the move."
7165 : "The combos used by the following combo pools will be partially or completely overwritten by this process."
7166 ));
7167 for(auto q = 0; q < MAXCOMBOPOOLS; ++q)
7168 {
7169 combo_pool& pool = combo_pools[q];
7170 int idx = 0;
7171 for(cpool_entry& cp : pool.combos)
7172 ADDC(&cp.cid, fmt::format("{} index {}", q, idx++));
7173 }
7174
7175 if(!movelist->check_prot())
7176 return false;
7177 }
7178 //Auto Combos
7179 {
7180 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7181 combo_links, dest_process, source_process,
7182 move
7183 ? "The combos used by the following autocombos will be partially cleared by the move."
7184 : "The combos used by the following autocombos will be partially or completely overwritten by this process."
7185 ));
7186 for (auto q = 0; q < MAXAUTOCOMBOS; ++q)
7187 {
7188 combo_auto& cauto = combo_autos[q];
7189 int idx = 0;
7190 for (autocombo_entry& ac : cauto.combos)
7191 ADDC(&ac.cid, fmt::format("{} index {}", q, idx++));
7192 ADDC(&cauto.cid_erase, fmt::format("{} Erase Combo", q));
7193 ADDC(&cauto.cid_display, fmt::format("{} Display Combo", q));
7194 }
7195
7196 if(!movelist->check_prot())
7197 return false;
7198 }
7199 //Combo Aliases
7200 {
7201 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7202 combo_links, dest_process, source_process,
7203 move
7204 ? "The combos used by the following aliases will be partially cleared by the move."
7205 : "The combos used by the following aliases will be partially or completely overwritten by this process."
7206 ));
7207 for(int32_t i=0; i<MAXCOMBOALIASES; i++)
7208 {
7209 //dimensions are 1 less than you would expect -DD
7210 int32_t count=(comboa_lmasktotal(combo_aliases[i].layermask)+1)*(combo_aliases[i].width+1)*(combo_aliases[i].height+1);
7211
7212 for(int32_t j=0; j<count; j++)
7213 {
7214 ADDC(&combo_aliases[i].combos[j], fmt::format("{} index {}", i, j));
7215 }
7216 }
7217
7218 if(!movelist->check_prot())
7219 return false;
7220 }
7221 //Favorite Combos
7222 {
7223 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7224 combo_links, dest_process, source_process,
7225 move
7226 ? "The combos used by the following favorite combos will be partially cleared by the move."
7227 : "The combos used by the following favorite combos will be partially or completely overwritten by this process."
7228 ));
7229 for(int32_t i=0; i<MAXFAVORITECOMBOS; i++)
7230 {
7231 if(favorite_combo_modes[i] != dm_normal) //don't hit pools/aliases/autos, only combos!
7232 continue;
7233 ADDC(&favorite_combos[i], fmt::format("Favorite {}", i));
7234 }
7235
7236 if(!movelist->check_prot())
7237 return false;
7238 }
7239 //Bottle Shops
7240 {
7241 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7242 combo_links, dest_process, source_process,
7243 move
7244 ? "The combos used by the following bottle shops will be partially cleared by the move."
7245 : "The combos used by the following bottle shops will be partially or completely overwritten by this process."
7246 ));
7247 for(auto q = 0; q < 256; ++q)
7248 for(auto p = 0; p < 3; ++p)
7249 ADDC(&QMisc.bottle_shop_types[q].comb[p], fmt::format("{} slot {}", q, p));
7250
7251 if(!movelist->check_prot())
7252 return false;
7253 }
7254 //Screens //EXPENSIVE! DO THIS LAST!
7255 {
7256 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7257 combo_links, dest_process, source_process,
7258 move
7259 ? "The combos used by the following screens will be partially cleared by the move."
7260 : "The combos used by the following screens will be partially or completely overwritten by this process."
7261 ));
7262
7263 for(int32_t i=0; i<map_count && i<MAXMAPS; i++)
7264 {
7265 for(int32_t j=0; j<MAPSCRS; j++)
7266 {
7267 mapscr& scr = TheMaps[i*MAPSCRS+j];
7268
7269 if(!(scr.valid&mVALID))
7270 continue;
7271
7272 ADDC(&scr.undercombo, fmt::format("{}x{:02X} - UnderCombo", i, j));
7273
7274 // Specifying the exact position is too expensive - too much string creation.
7275 std::string data_str = ComboProtection ? fmt::format("{}x{:02X} - Combo", i, j) : "";
7276 for(int32_t k=0; k<176; k++)
7277 ADDC(&scr.data[k], data_str);
7278
7279 for(int32_t k=0; k<128; k++)
7280 ADDC(&scr.secretcombo[k], fmt::format("{}x{:02X} - SecretCombo {}", i, j, k));
7281
7282 word maxffc = scr.numFFC();
7283 for(word k=0; k<maxffc; k++)
7284 {
7285 ffcdata& ffc = scr.ffcs[k];
7286 ADDC(&ffc.data, fmt::format("{}x{:02X} - FFC {}", i, j, k+1));
7287 }
7288 }
7289 }
7290
7291 if(!movelist->check_prot())
7292 return false;
7293 }
7294 if(source_process) //Apply the 'diff' value to all moved combos
7295 storage.redo();
7296 return true;
7297 }
7298
7299 bool handle_combo_move(ComboMoveProcess dest_process)
7300 {
7301 return _handle_combo_move(dest_process, nullopt, 0, nullptr);
7302 }
7303 bool handle_combo_move(ComboMoveProcess dest_process, ComboMoveProcess source_process, int diff, ComboMoveUndo& on_undo)
7304 {
7305 return _handle_combo_move(dest_process, source_process, diff, &on_undo);
7306 }
7307 void register_used_tiles()
7308 {
7309 memset(used_tile_table, 0, sizeof(used_tile_table));
7310 for_every_used_tile([&](int tile)
7311 {
7312 used_tile_table[tile] = true;
7313 });
7314 }
7315
7316 bool overlay_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move, int32_t cs, bool backwards)
7317 {
7318 bool ctrl=(CHECK_CTRL_CMD);
7319 bool copied=false;
7320 copied=overlay_tiles_united(tile,tile2,copy,copycnt,rect_sel,move,cs,backwards);
7321
7322 if(copied)
7323 {
7324 saved=false;
7325 }
7326
7327 return copied;
7328 }
7329
7330 bool overlay_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move, int32_t cs, bool backwards)
7331 {
7332 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7333 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7334
7335 // if tile>tile2 then swap them
7336 if(tile>tile2)
7337 {
7338 zc_swap(tile, tile2);
7339 }
7340
7341 // alt=copy from right
7342 // shift=copy from bottom
7343
7344 int32_t copies=copycnt;
7345 int32_t dest_first=tile;
7346 int32_t dest_last=tile2;
7347 int32_t src_first=copy;
7348 int32_t src_last=copy+copies-1;
7349
7350 int32_t dest_top=0;
7351 int32_t dest_bottom=0;
7352 int32_t src_top=0;
7353 int32_t src_bottom=0;
7354 int32_t src_left=0, src_right=0;
7355 int32_t src_width=0, src_height=0;
7356 int32_t dest_left=0, dest_right=0;
7357 int32_t dest_width=0, dest_height=0;
7358 int32_t rows=0, cols=0;
7359
7360 if(rect)
7361 {
7362 dest_top=TILEROW(dest_first);
7363 dest_bottom=TILEROW(dest_last);
7364 src_top=TILEROW(src_first);
7365 src_bottom=TILEROW(src_last);
7366
7367 src_left= zc_min(TILECOL(src_first),TILECOL(src_last));
7368 src_right=zc_max(TILECOL(src_first),TILECOL(src_last));
7369 src_first=(src_top * TILES_PER_ROW)+src_left;
7370 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7371
7372 dest_left= zc_min(TILECOL(dest_first),TILECOL(dest_last));
7373 dest_right=zc_max(TILECOL(dest_first),TILECOL(dest_last));
7374 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7375 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7376
7377 //if no dest range set, then set one
7378 if((dest_first==dest_last)&&(src_first!=src_last))
7379 {
7380 if(alt)
7381 {
7382 dest_left=dest_right-(src_right-src_left);
7383 }
7384 else
7385 {
7386 dest_right=dest_left+(src_right-src_left);
7387 }
7388
7389 if(shift)
7390 {
7391 dest_top=dest_bottom-(src_bottom-src_top);
7392 }
7393 else
7394 {
7395 dest_bottom=dest_top+(src_bottom-src_top);
7396 }
7397
7398 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7399 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7400 }
7401 else
7402 {
7403 if(dest_right-dest_left<src_right-src_left) //destination is shorter than source
7404 {
7405 if(alt) //copy from right tile instead of left
7406 {
7407 src_left=src_right-(dest_right-dest_left);
7408 }
7409 else //copy from left tile
7410 {
7411 src_right=src_left+(dest_right-dest_left);
7412 }
7413 }
7414 else if(dest_right-dest_left>src_right-src_left) //destination is longer than source
7415 {
7416 if(alt) //copy from right tile instead of left
7417 {
7418 dest_left=dest_right-(src_right-src_left);
7419 }
7420 else //copy from left tile
7421 {
7422 dest_right=dest_left+(src_right-src_left);
7423 }
7424 }
7425
7426 if(dest_bottom-dest_top<src_bottom-src_top) //destination is shorter than source
7427 {
7428 if(shift) //copy from bottom tile instead of top
7429 {
7430 src_top=src_bottom-(dest_bottom-dest_top);
7431 }
7432 else //copy from top tile
7433 {
7434 src_bottom=src_top+(dest_bottom-dest_top);
7435 }
7436 }
7437 else if(dest_bottom-dest_top>src_bottom-src_top) //destination is longer than source
7438 {
7439 if(shift) //copy from bottom tile instead of top
7440 {
7441 dest_top=dest_bottom-(src_bottom-src_top);
7442 }
7443 else //copy from top tile
7444 {
7445 dest_bottom=dest_top+(src_bottom-src_top);
7446 }
7447 }
7448
7449 src_first=(src_top * TILES_PER_ROW)+src_left;
7450 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7451 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7452 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7453 }
7454
7455 cols=src_right-src_left+1;
7456 rows=src_bottom-src_top+1;
7457
7458 dest_width=dest_right-dest_left+1;
7459 dest_height=dest_bottom-dest_top+1;
7460 src_width=src_right-src_left+1;
7461 src_height=src_bottom-src_top+1;
7462
7463 }
7464 else //!rect
7465 {
7466 //if no dest range set, then set one
7467 if((dest_first==dest_last)&&(src_first!=src_last))
7468 {
7469 if(alt)
7470 {
7471 dest_first=dest_last-(src_last-src_first);
7472 }
7473 else
7474 {
7475 dest_last=dest_first+(src_last-src_first);
7476 }
7477 }
7478 else
7479 {
7480 if(dest_last-dest_first<src_last-src_first) //destination is shorter than source
7481 {
7482 if(alt) //copy from last tile instead of first
7483 {
7484 src_first=src_last-(dest_last-dest_first);
7485 }
7486 else //copy from first tile
7487 {
7488 src_last=src_first+(dest_last-dest_first);
7489 }
7490 }
7491 else if(dest_last-dest_first>src_last-src_first) //destination is longer than source
7492 {
7493 if(alt) //copy from last tile instead of first
7494 {
7495 dest_first=dest_last-(src_last-src_first);
7496 }
7497 else //copy from first tile
7498 {
7499 dest_last=dest_first+(src_last-src_first);
7500 }
7501 }
7502 }
7503
7504 copies=dest_last-dest_first+1;
7505 }
7506
7507
7508
7509 char buf2[80], buf3[80], buf4[80];
7510 sprintf(buf2, " ");
7511 sprintf(buf3, " ");
7512 sprintf(buf4, " ");
7513
7514 // warn if range extends beyond last tile
7515 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7516
7517 if(dest_last>=NEWMAXTILES)
7518 {
7519 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7520 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7521 return false;
7522 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7523 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7524 // {
7525 // return false;
7526 // }
7527 }
7528
7529
7530 TileMoveUndo on_undo;
7531 // Overwrite warnings
7532 TileMoveProcess dest{rect, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last};
7533 if(move)
7534 {
7535 TileMoveProcess src{rect, src_left, src_top, src_width, src_height, src_first, src_last};
7536 if(!handle_tile_move(dest, src, dest_first-src_first, on_undo))
7537 return false;
7538 }
7539 else
7540 {
7541 if(!handle_tile_move(dest))
7542 return false;
7543 }
7544 // copy tiles and delete if needed (move)
7545
7546 {
7547 go_tiles();
7548
7549 int32_t diff=dest_first-src_first;
7550
7551 if(rect)
7552 {
7553 for(int32_t r=0; r<rows; ++r)
7554 {
7555 for(int32_t c=0; c<cols; ++c)
7556 {
7557 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
7558 int32_t st=(src_first+((r*TILES_PER_ROW)+c));
7559
7560 if(dt>=NEWMAXTILES)
7561 continue;
7562
7563 overlay_tile(newtilebuf,dt,st,cs,backwards);
7564
7565 }
7566 }
7567 }
7568 else
7569 {
7570 for(int32_t c=0; c<copies; ++c)
7571 {
7572 int32_t dt=(dest_first+c);
7573 int32_t st=(src_first+c);
7574
7575 if(dt>=NEWMAXTILES)
7576 continue;
7577
7578 overlay_tile(newtilebuf,dt,st,cs,backwards);
7579
7580 if(move)
7581 {
7582 if(st<dest_first||st>(dest_first+c-1))
7583 reset_tile(newtilebuf, st, tf4Bit);
7584 }
7585 }
7586 }
7587 }
7588
7589 //now that tiles have moved, fix these buffers -DD
7590 register_blank_tiles();
7591 register_used_tiles();
7592
7593 if(move)
7594 last_tile_move_list = std::move(on_undo);
7595 return true;
7596 }
7597 //
7598 bool do_movetile_united(tile_move_data const& tmd)
7599 {
7600 char buf2[80], buf3[80], buf4[80];
7601 sprintf(buf2, " ");
7602 sprintf(buf3, " ");
7603 sprintf(buf4, " ");
7604
7605 // warn if range extends beyond last tile
7606 sprintf(buf4, "Some tiles will not be %s", tmd.move?"moved.":"copied.");
7607
7608 if(tmd.dest_last>=NEWMAXTILES)
7609 {
7610 sprintf(buf4, "%s operation cancelled.", tmd.move?"Move":"Copy");
7611 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7612 return false;
7613 }
7614
7615 TileMoveUndo on_undo;
7616 // Overwrite warnings
7617 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7618 if(tmd.move)
7619 {
7620 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7621 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7622 return false;
7623 }
7624 else
7625 {
7626 if(!handle_tile_move(dest))
7627 return false;
7628 }
7629
7630 // copy tiles and delete if needed (tmd.move)
7631 {
7632 go_tiles();
7633
7634 if(tmd.rect)
7635 {
7636 for(int32_t r=0; r<tmd.rows; ++r)
7637 {
7638 for(int32_t c=0; c<tmd.cols; ++c)
7639 {
7640 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7641 int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7642
7643 if(dt>=NEWMAXTILES)
7644 continue;
7645
7646 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7647
7648 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7649 {
7650 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7651 }
7652
7653 if(tmd.move)
7654 {
7655 if((st<tmd.dest_first||st>tmd.dest_first+((tmd.rows-1)*TILES_PER_ROW)+(tmd.cols-1)))
7656 reset_tile(newtilebuf, st, tf4Bit);
7657 else
7658 {
7659 int32_t destLeft=tmd.dest_first%TILES_PER_ROW;
7660 int32_t destRight=(tmd.dest_first+tmd.cols-1)%TILES_PER_ROW;
7661 if(destLeft<=destRight)
7662 {
7663 if(st%TILES_PER_ROW<destLeft || st%TILES_PER_ROW>destRight)
7664 reset_tile(newtilebuf, st, tf4Bit);
7665 }
7666 else // Wrapped around
7667 {
7668 if(st%TILES_PER_ROW<destLeft && st%TILES_PER_ROW>destRight)
7669 reset_tile(newtilebuf, st, tf4Bit);
7670 }
7671 }
7672 }
7673 }
7674 }
7675 }
7676 else
7677 {
7678 for(int32_t c=0; c<tmd.copies; ++c)
7679 {
7680 int32_t dt=(tmd.dest_first+c);
7681 int32_t st=(tmd.src_first+c);
7682
7683 if(dt>=NEWMAXTILES)
7684 continue;
7685
7686 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7687
7688 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7689 {
7690 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7691 }
7692
7693 if(tmd.move)
7694 {
7695 if(st<tmd.dest_first||st>(tmd.dest_first+c-1))
7696 reset_tile(newtilebuf, st, tf4Bit);
7697 }
7698 }
7699 }
7700 }
7701
7702 //now that tiles have moved, fix these buffers -DD
7703 register_blank_tiles();
7704 register_used_tiles();
7705
7706 if(tmd.move)
7707 last_tile_move_list = std::move(on_undo);
7708 return true;
7709 }
7710
7711 bool copy_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7712 {
7713 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7714 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7715
7716 // if tile>tile2 then swap them
7717 if(tile>tile2)
7718 {
7719 zc_swap(tile, tile2);
7720 }
7721
7722 // alt=copy from right
7723 // shift=copy from bottom
7724 tile_move_data tmd;
7725
7726 tmd.copies=copycnt;
7727 tmd.dest_first=tile;
7728 tmd.dest_last=tile2;
7729 tmd.src_first=copy;
7730 tmd.src_last=copy+tmd.copies-1;
7731 tmd.rect = rect;
7732 tmd.move = move;
7733
7734 if(rect)
7735 {
7736 tmd.dest_top=TILEROW(tmd.dest_first);
7737 tmd.dest_bottom=TILEROW(tmd.dest_last);
7738 tmd.src_top=TILEROW(tmd.src_first);
7739 tmd.src_bottom=TILEROW(tmd.src_last);
7740
7741 tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7742 tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7743 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7744 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7745
7746 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7747 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7748 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7749 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7750
7751 //if no dest range set, then set one
7752 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7753 {
7754 if(alt)
7755 {
7756 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7757 }
7758 else
7759 {
7760 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7761 }
7762
7763 if(shift)
7764 {
7765 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7766 }
7767 else
7768 {
7769 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7770 }
7771
7772 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7773 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7774 }
7775 else
7776 {
7777 if(tmd.dest_right-tmd.dest_left<tmd.src_right-tmd.src_left) //destination is shorter than source
7778 {
7779 if(alt) //copy from right tile instead of left
7780 {
7781 tmd.src_left=tmd.src_right-(tmd.dest_right-tmd.dest_left);
7782 }
7783 else //copy from left tile
7784 {
7785 tmd.src_right=tmd.src_left+(tmd.dest_right-tmd.dest_left);
7786 }
7787 }
7788 else if(tmd.dest_right-tmd.dest_left>tmd.src_right-tmd.src_left) //destination is longer than source
7789 {
7790 if(alt) //copy from right tile instead of left
7791 {
7792 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7793 }
7794 else //copy from left tile
7795 {
7796 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7797 }
7798 }
7799
7800 if(tmd.dest_bottom-tmd.dest_top<tmd.src_bottom-tmd.src_top) //destination is shorter than source
7801 {
7802 if(shift) //copy from bottom tile instead of top
7803 {
7804 tmd.src_top=tmd.src_bottom-(tmd.dest_bottom-tmd.dest_top);
7805 }
7806 else //copy from top tile
7807 {
7808 tmd.src_bottom=tmd.src_top+(tmd.dest_bottom-tmd.dest_top);
7809 }
7810 }
7811 else if(tmd.dest_bottom-tmd.dest_top>tmd.src_bottom-tmd.src_top) //destination is longer than source
7812 {
7813 if(shift) //copy from bottom tile instead of top
7814 {
7815 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7816 }
7817 else //copy from top tile
7818 {
7819 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7820 }
7821 }
7822
7823 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7824 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7825 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7826 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7827 }
7828
7829 tmd.cols=tmd.src_right-tmd.src_left+1;
7830 tmd.rows=tmd.src_bottom-tmd.src_top+1;
7831
7832 tmd.dest_width=tmd.dest_right-tmd.dest_left+1;
7833 tmd.dest_height=tmd.dest_bottom-tmd.dest_top+1;
7834 tmd.src_width=tmd.src_right-tmd.src_left+1;
7835 tmd.src_height=tmd.src_bottom-tmd.src_top+1;
7836
7837 }
7838 else //!rect
7839 {
7840 //if no dest range set, then set one
7841 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7842 {
7843 if(alt)
7844 {
7845 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7846 }
7847 else
7848 {
7849 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7850 }
7851 }
7852 else
7853 {
7854 if(tmd.dest_last-tmd.dest_first<tmd.src_last-tmd.src_first) //destination is shorter than source
7855 {
7856 if(alt) //copy from last tile instead of first
7857 {
7858 tmd.src_first=tmd.src_last-(tmd.dest_last-tmd.dest_first);
7859 }
7860 else //copy from first tile
7861 {
7862 tmd.src_last=tmd.src_first+(tmd.dest_last-tmd.dest_first);
7863 }
7864 }
7865 else if(tmd.dest_last-tmd.dest_first>tmd.src_last-tmd.src_first) //destination is longer than source
7866 {
7867 if(alt) //copy from last tile instead of first
7868 {
7869 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7870 }
7871 else //copy from first tile
7872 {
7873 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7874 }
7875 }
7876 }
7877
7878 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7879 }
7880
7881 return do_movetile_united(tmd);
7882 }
7883
7884 //
7885
7886 bool copy_tiles_united_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7887 {
7888 assert(!move); //not implemented
7889
7890 // if tile>tile2 then swap them
7891 if(tile>tile2)
7892 {
7893 zc_swap(tile, tile2);
7894 }
7895
7896 tile_move_data tmd;
7897 tmd.copies=copycnt;
7898 tmd.dest_first=tile;
7899 tmd.dest_last=tile2;
7900 tmd.src_first=copy;
7901 tmd.src_last=copy+tmd.copies-1;
7902
7903
7904
7905 if(rect)
7906 {
7907 tmd.dest_top=TILEROW(tmd.dest_first);
7908 tmd.dest_bottom=TILEROW(tmd.dest_last);
7909 //tmd.src_top=TILEROW(tmd.src_first);
7910 //tmd.src_bottom=TILEROW(tmd.src_last);
7911
7912 //tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7913 //tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7914 //tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7915 //tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7916
7917 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7918 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7919 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7920 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7921
7922
7923
7924
7925 tmd.dest_width=tmd.dest_right-tmd.dest_left;
7926 tmd.dest_height=tmd.dest_bottom-tmd.dest_top;
7927
7928 tmd.cols=tmd.dest_width+1;
7929 tmd.rows=tmd.dest_height+1;
7930
7931 al_trace("tmd.rows: %d\n", tmd.rows);
7932 al_trace("tmd.cols: %d\n", tmd.cols);
7933
7934
7935 }
7936 else //!rect
7937 {
7938 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7939 }
7940
7941
7942
7943 char buf2[80], buf3[80], buf4[80];
7944 sprintf(buf2, " ");
7945 sprintf(buf3, " ");
7946 sprintf(buf4, " ");
7947
7948 // warn if range extends beyond last tile
7949 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7950
7951 if(tmd.dest_last>=NEWMAXTILES)
7952 {
7953 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7954 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7955 return false;
7956 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7957 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7958 // {
7959 // return false;
7960 // }
7961 }
7962
7963 TileMoveUndo on_undo;
7964 // Overwrite warnings
7965 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7966 if(tmd.move)
7967 {
7968 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7969 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7970 return false;
7971 }
7972 else
7973 {
7974 if(!handle_tile_move(dest))
7975 return false;
7976 }
7977
7978 // copy tiles and delete if needed (move)
7979
7980 {
7981 go_tiles();
7982
7983 int32_t diff=tmd.dest_first-tmd.src_first;
7984
7985 if(rect)
7986 {
7987 al_trace("floodfill, rect\n");
7988 al_trace("tmd.rows: %d\n", tmd.rows);
7989 al_trace("tmd.cols: %d\n", tmd.cols);
7990 for(int32_t r=0; r<tmd.rows; ++r)
7991 {
7992 for(int32_t c=0; c<tmd.cols; ++c)
7993 {
7994 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7995 //int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7996
7997 if(dt>=NEWMAXTILES)
7998 continue;
7999
8000 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
8001
8002 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
8003 {
8004 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
8005 }
8006 }
8007 }
8008 }
8009 else
8010 {
8011 for(int32_t c=0; c<tmd.copies; ++c)
8012 {
8013 int32_t dt=(tmd.dest_first+c);
8014 int32_t st=(tmd.src_first+c);
8015
8016 if(dt>=NEWMAXTILES)
8017 continue;
8018
8019 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
8020
8021 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
8022 {
8023 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
8024 }
8025
8026 }
8027 }
8028 }
8029
8030 //now that tiles have moved, fix these buffers -DD
8031 register_blank_tiles();
8032 register_used_tiles();
8033
8034 if(tmd.move)
8035 last_tile_move_list = std::move(on_undo);
8036 return true;
8037 }
8038 //
8039
8040 bool copy_tiles_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
8041 {
8042 al_trace("Floodfill Psste\n");
8043 bool ctrl=(CHECK_CTRL_CMD);
8044 bool copied=false;
8045 copied=copy_tiles_united_floodfill(tile,tile2,copy,copycnt,rect_sel,move);
8046
8047 if(copied)
8048 {
8049 if(!ctrl)
8050 {
8051 copy=-1;
8052 tile2=tile;
8053 }
8054
8055 saved=false;
8056 }
8057
8058 return copied;
8059 }
8060
8061 bool copy_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
8062 {
8063 bool ctrl=(CHECK_CTRL_CMD);
8064 bool copied=false;
8065 copied=copy_tiles_united(tile,tile2,copy,copycnt,rect_sel,move);
8066
8067 if(copied)
8068 {
8069 if(!ctrl)
8070 {
8071 copy=-1;
8072 tile2=tile;
8073 }
8074
8075 saved=false;
8076 }
8077
8078 return copied;
8079 }
8080
8081 bool scale_or_rotate_tiles(int32_t &tile, int32_t &tile2, int32_t &cs, bool rotate)
8082 {
8083 // if tile>tile2 then swap them
8084 if(tile>tile2)
8085 {
8086 zc_swap(tile, tile2);
8087 }
8088 int32_t src_top = TILEROW(tile);
8089 int32_t src_bottom = TILEROW(tile2);
8090 int32_t src_left = zc_min(TILECOL(tile),TILECOL(tile2));
8091 int32_t src_right = zc_max(TILECOL(tile),TILECOL(tile2));
8092 int32_t src_first = (src_top * TILES_PER_ROW)+src_left;
8093 int32_t src_last = (src_bottom*TILES_PER_ROW)+src_right;
8094
8095 int32_t src_width = src_right-src_left+1,
8096 src_height = src_bottom-src_top+1;
8097 int32_t dest_width = src_width, dest_height = src_height;
8098 zfix dest_rot = 0_zf;
8099 if(rotate)
8100 RotateTileDialog(&dest_width, &dest_height, &dest_rot).show();
8101 else
8102 ScaleTileDialog(&dest_width, &dest_height).show();
8103 if (rotate)
8104 {
8105 if (dest_rot == 0) return false;
8106 }
8107 else
8108 {
8109 if (dest_width == src_width && dest_height == src_height) return false; //no scaling
8110 }
8111 dest_width = vbound(dest_width, 1, 20);
8112 dest_height = vbound(dest_height, 1, 20);
8113
8114 int32_t dest_top = src_top;
8115 int32_t dest_bottom = src_top+dest_height-1;
8116 int32_t dest_left = src_left;
8117 int32_t dest_right = src_left+dest_width-1;
8118 int32_t dest_first = src_first;
8119 int32_t dest_last = (dest_bottom*TILES_PER_ROW)+dest_right;
8120
8121
8122 if(dest_last>=NEWMAXTILES)
8123 {
8124 InfoDialog("Destination Error", "The destination extends beyond the last available tile row. Scale operation cancelled.").show();
8125 return false;
8126 }
8127
8128 // Overwrite warnings
8129 if(!handle_tile_move({true, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last}))
8130 return false;
8131
8132 //Do the rotate
8133 {
8134 go_tiles();
8135
8136 int32_t diff=dest_first-src_first;
8137 BITMAP *srcbmp = create_bitmap_ex(8,src_width*16,src_height*16),
8138 *destbmp = create_bitmap_ex(8,dest_width*16,dest_height*16);
8139 clear_bitmap(srcbmp); clear_bitmap(destbmp);
8140 overtileblock16(srcbmp, src_first, 0, 0, src_width, src_height, cs, 0);
8141 bool is8bit = newtilebuf[src_first].format == tf8Bit;
8142 if (rotate)
8143 {
8144 rotate_sprite(destbmp, srcbmp, 0, 0, ftofix(dest_rot * 0.7111111111111));
8145 }
8146 else
8147 {
8148 stretch_blit(srcbmp, destbmp, 0, 0, srcbmp->w, srcbmp->h,
8149 0, 0, destbmp->w, destbmp->h);
8150 }
8151 int32_t mhei = zc_max(src_height,dest_height),
8152 mwid = zc_max(src_width, dest_width);
8153 for(int32_t r=0; r<mhei; ++r)
8154 {
8155 for(int32_t c=0; c<mwid; ++c)
8156 {
8157 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
8158
8159 if(dt>=NEWMAXTILES)
8160 continue;
8161 if(r < dest_height && c < dest_width)
8162 {
8163 write_tile(newtilebuf, destbmp, dt, c*16, r*16, is8bit, false);
8164 }
8165 else reset_tile(newtilebuf, dt, tf4Bit);
8166 }
8167 }
8168 }
8169
8170 register_blank_tiles();
8171 register_used_tiles();
8172 return true;
8173 }
8174
8175 void copy_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool masscopy)
8176 {
8177 //these 2 shouldn't be needed, but just to be safe...
8178 reset_combo_animations();
8179 reset_combo_animations2();
8180
8181 if(tile2<tile)
8182 {
8183 zc_swap(tile,tile2);
8184 }
8185
8186 auto first = tile;
8187 auto last = masscopy ? tile2 : first + copycnt-1;
8188 if(!handle_combo_move({first,last}))
8189 return;
8190
8191 if(!masscopy)
8192 {
8193 if(tile==copy)
8194 {
8195 copy=-1;
8196 tile2=tile;
8197 return;
8198 }
8199
8200 // go_combos(); // commented because caller does it for us
8201 //if copying to an earlier combo, copy from left to right
8202 //otherwise, copy from right to left
8203 for(int32_t t=(tile<copy)?0:(copycnt-1); (tile<copy)?(t<copycnt):(t>=0); (tile<copy)?(t++):(t--))
8204 {
8205 if(tile+t < MAXCOMBOS)
8206 {
8207 combobuf[tile+t]=combobuf[copy+t];
8208 }
8209 }
8210
8211 copy=-1;
8212 tile2=tile;
8213 saved=false;
8214 }
8215 else
8216 {
8217 // go_combos();
8218 int32_t src=copy, dest=tile;
8219
8220 do
8221 {
8222 combobuf[dest]=combobuf[src];
8223 ++src;
8224 ++dest;
8225
8226 if((src-copy)==copycnt) src=copy;
8227 }
8228 while(dest<=tile2);
8229
8230 copy=-1;
8231 tile2=tile;
8232 saved=false;
8233 }
8234
8235 setup_combo_animations();
8236 setup_combo_animations2();
8237 }
8238
8239 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing)
8240 {
8241 reset_combo_animations();
8242 reset_combo_animations2();
8243 go_combos();
8244
8245 auto diff = cmd.tile - cmd.copy1;
8246 if(is_undoing)
8247 on_undo.undo();
8248 else if(!handle_combo_move({cmd.tile,cmd.tile+cmd.copycnt-1},{cmd.copy1,cmd.copy1+cmd.copycnt-1}, diff, on_undo))
8249 return false;
8250
8251 for(int32_t t=(cmd.tile<cmd.copy1)?0:(cmd.copycnt-1); (cmd.tile<cmd.copy1)?(t<cmd.copycnt):(t>=0); (cmd.tile<cmd.copy1)?(t++):(t--))
8252 {
8253 if(cmd.tile+t < MAXCOMBOS)
8254 {
8255 combobuf[cmd.tile+t]=combobuf[cmd.copy1+t];
8256 clear_combo(cmd.copy1+t);
8257 }
8258 }
8259
8260 setup_combo_animations();
8261 setup_combo_animations2();
8262 saved=false;
8263 return true;
8264 }
8265
8266 void move_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt)
8267 {
8268 if(tile2<tile)
8269 {
8270 zc_swap(tile,tile2);
8271 }
8272
8273 if(tile==copy)
8274 {
8275 copy=-1;
8276 tile2=tile;
8277 return;
8278 }
8279
8280 combo_move_data cmd;
8281 cmd.tile = tile;
8282 cmd.tile2 = tile2;
8283 cmd.copy1 = copy;
8284 cmd.copycnt = copycnt;
8285
8286 ComboMoveUndo on_undo;
8287 if(!do_movecombo(cmd, on_undo))
8288 return;
8289 last_combo_move_list = std::move(on_undo);
8290 copy=-1;
8291 tile2=tile;
8292 }
8293
8294 void do_delete_tiles(int32_t firsttile, int32_t lasttile, bool rect_sel)
8295 {
8296 if(firsttile > lasttile)
8297 zc_swap(firsttile,lasttile);
8298 int32_t coldiff = 0;
8299 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8300 {
8301 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8302 firsttile-=coldiff;
8303 lasttile+=coldiff;
8304 }
8305 for(int32_t t=firsttile; t<=lasttile; ++t)
8306 if(!rect_sel ||
8307 ((TILECOL(t)>=TILECOL(firsttile)) &&
8308 (TILECOL(t)<=TILECOL(lasttile))))
8309 reset_tile(newtilebuf, t, tf4Bit);
8310 saved=false;
8311 register_blank_tiles();
8312 }
8313
8314 void delete_tiles(int32_t &tile,int32_t &tile2,bool rect_sel)
8315 {
8316 char buf[40];
8317
8318 if(tile==tile2)
8319 {
8320 sprintf(buf,"Delete tile %d?",tile);
8321 }
8322 else
8323 {
8324 sprintf(buf,"Delete tiles %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
8325 }
8326
8327 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8328 {
8329 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8330
8331 go_tiles();
8332
8333 //if copying to an earlier tile, copy from left to right
8334 //otherwise, copy from right to left
8335 do_delete_tiles(firsttile, lasttile, rect_sel);
8336
8337 tile=tile2=zc_min(tile,tile2);
8338 saved=false;
8339 register_blank_tiles();
8340 }
8341 }
8342
8343 void overlay_tile2(int32_t dest,int32_t src,int32_t cs,bool backwards)
8344 {
8345 byte buf[256];
8346 go_tiles();
8347
8348 unpack_tile(newtilebuf, dest, 0, false);
8349
8350 for(int32_t i=0; i<256; i++)
8351 buf[i] = unpackbuf[i];
8352
8353 unpack_tile(newtilebuf, src, 0, false);
8354
8355 if(newtilebuf[src].format>tf4Bit)
8356 {
8357 cs=0;
8358 }
8359
8360 cs &= 15;
8361 cs <<= CSET_SHFT;
8362
8363 for(int32_t i=0; i<256; i++)
8364 {
8365 if(backwards)
8366 {
8367 if(!buf[i])
8368 {
8369 buf[i] = unpackbuf[i]+cs;
8370 }
8371 }
8372 else
8373 {
8374 if(unpackbuf[i])
8375 {
8376 buf[i] = unpackbuf[i]+cs;
8377 }
8378 }
8379 }
8380
8381 pack_tile(newtilebuf, buf,dest);
8382 saved=false;
8383 }
8384
8385 void mass_overlay_tile(int32_t dest1, int32_t dest2, int32_t src, int32_t cs, bool backwards, bool rect_sel)
8386 {
8387 //byte buf[256];
8388 go_tiles();
8389
8390 if(!rect_sel)
8391 {
8392 for(int32_t d=dest1; d <= dest2; ++d)
8393 {
8394 /*unpack_tile(newtilebuf, d, 0, false);
8395
8396 for(int32_t i=0; i<256; i++)
8397 {
8398 if(!backwards)
8399 {
8400 if(!buf[i])
8401 {
8402 buf[i] = unpackbuf[i] + cs;
8403 }
8404 }
8405 else
8406 {
8407 if(unpackbuf[i])
8408 {
8409 buf[i] = unpackbuf[i] + cs;
8410 }
8411 }
8412 }
8413
8414 pack_tile(newtilebuf, buf,d);
8415 */
8416
8417 overlay_tile(newtilebuf,d,src,cs,backwards);
8418
8419 if(!blank_tile_table[src])
8420 {
8421 blank_tile_table[d]=false;
8422 }
8423 }
8424 }
8425 else
8426 {
8427 int32_t rmin=zc_min(TILEROW(dest1),TILEROW(dest2));
8428 int32_t rmax=zc_max(TILEROW(dest1),TILEROW(dest2));
8429 int32_t cmin=zc_min(TILECOL(dest1),TILECOL(dest2));
8430 int32_t cmax=zc_max(TILECOL(dest1),TILECOL(dest2));
8431 int32_t d=0;
8432
8433 for(int32_t j=cmin; j<=cmax; ++j)
8434 {
8435 for(int32_t k=rmin; k<=rmax; ++k)
8436 {
8437 d=j+TILES_PER_ROW*k;
8438 /*unpack_tile(newtilebuf, d, 0, false);
8439
8440 for(int32_t i=0; i<256; i++)
8441 {
8442 if(!backwards)
8443 {
8444 if(!buf[i])
8445 {
8446 buf[i] = unpackbuf[i] + cs;
8447 }
8448 }
8449 else
8450 {
8451 if(unpackbuf[i])
8452 {
8453 buf[i] = unpackbuf[i] + cs;
8454 }
8455 }
8456 }
8457
8458 pack_tile(newtilebuf, buf,d);
8459 */
8460
8461 overlay_tile(newtilebuf,d,src,cs,backwards);
8462
8463 if(!blank_tile_table[src])
8464 {
8465 blank_tile_table[d]=false;
8466 }
8467 }
8468 }
8469 }
8470
8471 return;
8472 }
8473
8474 void sel_tile(int32_t &tile, int32_t &tile2, int32_t &first, int32_t type, int32_t s)
8475 {
8476 tile+=s;
8477 bound(tile,0,NEWMAXTILES-1);
8478
8479 if(type!=0 || !(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
8480 tile2 = tile;
8481
8482 first = tile - (tile%TILES_PER_PAGE);
8483 }
8484
8485 void convert_tile(int32_t t, int32_t bp2, int32_t cs, bool shift, bool alt)
8486 {
8487 int32_t cst;
8488
8489 switch(bp2)
8490 {
8491 case tf4Bit:
8492 switch(newtilebuf[t].format)
8493 {
8494 case tf4Bit:
8495 //already in the right format
8496 break;
8497
8498 case tf8Bit:
8499 unpack_tile(newtilebuf, t, 0, true);
8500
8501 if(alt) //reduce
8502 {
8503 for(int32_t i=0; i<256; i++)
8504 {
8505 if(!shift||unpackbuf[i]!=0)
8506 {
8507 unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
8508 }
8509 }
8510 }
8511 else //truncate
8512 {
8513 for(int32_t i=0; i<256; i++)
8514 {
8515 unpackbuf[i]&=15;
8516 }
8517 }
8518
8519 reset_tile(newtilebuf, t, tf4Bit);
8520 pack_tile(newtilebuf, unpackbuf, t);
8521 break;
8522 }
8523
8524 break;
8525
8526 case tf8Bit:
8527 switch(newtilebuf[t].format)
8528 {
8529 case tf4Bit:
8530 unpack_tile(newtilebuf, t, 0, true);
8531 cst = cs&15;
8532 cst <<= CSET_SHFT;
8533
8534 for(int32_t i=0; i<256; i++)
8535 {
8536 if(!shift||unpackbuf[i]!=0)
8537 {
8538 unpackbuf[i]+=cst;
8539 }
8540 }
8541
8542 reset_tile(newtilebuf, t, tf8Bit);
8543 pack_tile(newtilebuf, unpackbuf, t);
8544 break;
8545
8546 case tf8Bit:
8547 //already in the right format
8548 break;
8549 }
8550
8551 break;
8552 }
8553 }
8554
8555 static DIALOG create_relational_tiles_dlg[] =
8556 {
8557 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
8558 12 { jwin_win_proc, 0, 0, 160, 92, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Tile Setup", NULL, NULL },
8559 12 { jwin_rtext_proc, 74, 28, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Frames:", NULL, NULL },
8560 12 { jwin_edit_proc, 78, 24, 48, 16, 0, 0, 0, 0, 6, 0, NULL, NULL, NULL },
8561 12 { jwin_radio_proc, 8, 44, 64, 9, vc(14), vc(1), 0, D_SELECTED, 0, 0, (void *) "Relational", NULL, NULL },
8562 12 { jwin_radio_proc, 68, 44, 64, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "Dungeon Carving", NULL, NULL },
8563 12 { jwin_button_proc, 10, 66, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
8564 12 { jwin_button_proc, 90, 66, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
8565 12 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
8566 12 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
8567 };
8568
8569 void draw_tile_list_window()
8570 {
8571 int32_t w = 640;
8572 int32_t h = 480;
8573
8574 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8575 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
8576 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
8577 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
8578
8579 FONT *oldfont = font;
8580 font = get_zc_font(font_lfont);
8581 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Tile", true);
8582 font=oldfont;
8583 return;
8584 }
8585
8586 void show_blank_tile(int32_t t)
8587 {
8588 char tbuf[80], tbuf2[80], tbuf3[80];
8589 sprintf(tbuf, "Tile is%s blank.", blank_tile_table[t]?"":" not");
8590 sprintf(tbuf2, "%c %c", blank_tile_quarters_table[t*4]?'X':'-', blank_tile_quarters_table[(t*4)+1]?'X':'-');
8591 sprintf(tbuf3, "%c %c", blank_tile_quarters_table[(t*4)+2]?'X':'-', blank_tile_quarters_table[(t*4)+3]?'X':'-');
8592 jwin_alert("Blank Tile Information",tbuf,tbuf2,tbuf3,"&OK",NULL,13,27,get_zc_font(font_lfont));
8593 }
8594
8595 static void do_convert_tile(int32_t tile, int32_t tile2, int32_t cs, bool rect_sel, int format, bool shift, bool alt, bool skip_prompt = false)
8596 {
8597 int num_bits;
8598 if (format == tf4Bit)
8599 num_bits = 4;
8600 else if (format == tf8Bit)
8601 num_bits = 8;
8602 else assert(false);
8603
8604 char buf[80];
8605 sprintf(buf, "Do you want to convert the selected %s to %d-bit color?", tile==tile2?"tile":"tiles",num_bits);
8606
8607 if (skip_prompt || jwin_alert("Convert Tile?",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8608 {
8609 go_tiles();
8610 saved=false;
8611
8612 if(format == tf4Bit)
8613 {
8614 memset(cset_reduce_table, 0, 256);
8615 memset(col_diff,0,3*128);
8616 calc_cset_reduce_table(RAMpal, cs);
8617 }
8618
8619 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8620
8621 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8622 {
8623 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8624 firsttile-=coldiff;
8625 lasttile+=coldiff;
8626 }
8627
8628 for(int32_t t=firsttile; t<=lasttile; t++)
8629 if(!rect_sel ||
8630 ((TILECOL(t)>=TILECOL(firsttile)) &&
8631 (TILECOL(t)<=TILECOL(lasttile))))
8632 convert_tile(t, format, cs, shift, alt);
8633
8634 tile=tile2=zc_min(tile,tile2);
8635 }
8636 }
8637
8638
8639 int32_t readtilefile(PACKFILE *f)
8640 {
8641 dword section_version=0;
8642 int32_t zversion = 0;
8643 int32_t zbuild = 0;
8644
8645 if(!p_igetl(&zversion,f))
8646 {
8647 return 0;
8648 }
8649 if(!p_igetl(&zbuild,f))
8650 {
8651 return 0;
8652 }
8653 if(!p_igetw(&section_version,f))
8654 {
8655 return 0;
8656 }
8657 if(!read_deprecated_section_cversion(f))
8658 {
8659 return 0;
8660 }
8661 al_trace("readoneweapon section_version: %d\n", section_version);
8662
8663 if ( zversion > ZELDA_VERSION )
8664 {
8665 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8666 return 0;
8667 }
8668
8669 else if ( ( section_version > V_TILES ))
8670 {
8671 al_trace("Cannot read .ztile packfile made using V_TILES (%d)\n", section_version);
8672 return 0;
8673
8674 }
8675 else
8676 {
8677 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8678 }
8679
8680 int32_t index = 0;
8681 int32_t count = 0;
8682
8683 //tile id
8684 if(!p_igetl(&index,f))
8685 {
8686 return 0;
8687 }
8688 al_trace("Reading tile: index(%d)\n", index);
8689
8690 //tile count
8691 if(!p_igetl(&count,f))
8692 {
8693 return 0;
8694 }
8695 al_trace("Reading tile: count(%d)\n", count);
8696
8697
8698
8699
8700 for ( int32_t tilect = 0; tilect < count; tilect++ )
8701 {
8702 byte *temp_tile = new byte[tilesize(tf32Bit)];
8703 byte format=tf4Bit;
8704 memset(temp_tile, 0, tilesize(tf32Bit));
8705 if(!p_getc(&format,f))
8706 {
8707 delete[] temp_tile;
8708 return 0;
8709 }
8710
8711
8712 if(!pfread(temp_tile,tilesize(format),f))
8713 {
8714 delete[] temp_tile;
8715 return 0;
8716 }
8717
8718 reset_tile(newtilebuf, index+(tilect), format);
8719 memcpy(newtilebuf[index+(tilect)].data,temp_tile,tilesize(newtilebuf[index+(tilect)].format));
8720 delete[] temp_tile;
8721 }
8722
8723
8724 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8725
8726 register_blank_tiles();
8727 register_used_tiles();
8728
8729 return 1;
8730
8731 }
8732
8733 int32_t readtilefile_to_location(PACKFILE *f, int32_t start, int32_t skip)
8734 {
8735 dword section_version=0;
8736 int32_t zversion = 0;
8737 int32_t zbuild = 0;
8738
8739 if(!p_igetl(&zversion,f))
8740 {
8741 return 0;
8742 }
8743 if(!p_igetl(&zbuild,f))
8744 {
8745 return 0;
8746 }
8747 if(!p_igetw(&section_version,f))
8748 {
8749 return 0;
8750 }
8751 if(!read_deprecated_section_cversion(f))
8752 {
8753 return 0;
8754 }
8755 al_trace("readoneweapon section_version: %d\n", section_version);
8756
8757 if ( zversion > ZELDA_VERSION )
8758 {
8759 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8760 return 0;
8761 }
8762
8763 else if ( ( section_version > V_TILES ))
8764 {
8765 al_trace("Cannot read .ztile packfile made using V_TILES (%d)\n", section_version);
8766 return 0;
8767
8768 }
8769 else
8770 {
8771 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8772 }
8773
8774 int32_t index = 0;
8775 int32_t count = 0;
8776
8777 //tile id
8778 if(!p_igetl(&index,f))
8779 {
8780 return 0;
8781 }
8782 al_trace("Reading tile: index(%d)\n", index);
8783
8784 //tile count
8785 if(!p_igetl(&count,f))
8786 {
8787 return 0;
8788 }
8789 al_trace("Reading tile: count(%d)\n", count);
8790
8791
8792 for ( int32_t tilect = 0; tilect < count; tilect++ )
8793 {
8794 byte *temp_tile = new byte[tilesize(tf32Bit)];
8795 byte format=tf4Bit;
8796 memset(temp_tile, 0, tilesize(tf32Bit));
8797 if(!p_getc(&format,f))
8798 {
8799 delete[] temp_tile;
8800 return 0;
8801 }
8802
8803
8804 if(!pfread(temp_tile,tilesize(format),f))
8805 {
8806 delete[] temp_tile;
8807 return 0;
8808 }
8809
8810 reset_tile(newtilebuf, start+(tilect), format);
8811 if ( skip )
8812 {
8813 if ( (start+(tilect)) < skip )
8814 {
8815 delete[] temp_tile;
8816 continue;
8817 }
8818
8819 }
8820 if ( start+(tilect) < NEWMAXTILES )
8821 {
8822 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8823 }
8824 delete[] temp_tile;
8825
8826 }
8827
8828
8829 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8830
8831 register_blank_tiles();
8832 register_used_tiles();
8833
8834 return 1;
8835
8836 }
8837
8838
8839 int32_t readtilefile_to_location(PACKFILE *f, int32_t start)
8840 {
8841 dword section_version=0;
8842 int32_t zversion = 0;
8843 int32_t zbuild = 0;
8844
8845 if(!p_igetl(&zversion,f))
8846 {
8847 return 0;
8848 }
8849 if(!p_igetl(&zbuild,f))
8850 {
8851 return 0;
8852 }
8853 if(!p_igetw(&section_version,f))
8854 {
8855 return 0;
8856 }
8857 if(!read_deprecated_section_cversion(f))
8858 {
8859 return 0;
8860 }
8861 al_trace("readoneweapon section_version: %d\n", section_version);
8862
8863 if ( zversion > ZELDA_VERSION )
8864 {
8865 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8866 return 0;
8867 }
8868
8869 else if ( ( section_version > V_TILES ))
8870 {
8871 al_trace("Cannot read .ztile packfile made using V_TILES (%d)\n", section_version);
8872 return 0;
8873
8874 }
8875 else
8876 {
8877 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8878 }
8879
8880 int32_t index = 0;
8881 int32_t count = 0;
8882
8883 //tile id
8884 if(!p_igetl(&index,f))
8885 {
8886 return 0;
8887 }
8888 al_trace("Reading tile: index(%d)\n", index);
8889
8890 //tile count
8891 if(!p_igetl(&count,f))
8892 {
8893 return 0;
8894 }
8895 al_trace("Reading tile: count(%d)\n", count);
8896
8897
8898
8899
8900 for ( int32_t tilect = 0; tilect < count; tilect++ )
8901 {
8902 byte *temp_tile = new byte[tilesize(tf32Bit)];
8903 byte format=tf4Bit;
8904 memset(temp_tile, 0, tilesize(tf32Bit));
8905
8906 if(!p_getc(&format,f))
8907 {
8908 delete[] temp_tile;
8909 return 0;
8910 }
8911
8912
8913 if(!pfread(temp_tile,tilesize(format),f))
8914 {
8915 delete[] temp_tile;
8916 return 0;
8917 }
8918
8919 reset_tile(newtilebuf, start+(tilect), format);
8920 if ( start+(tilect) < NEWMAXTILES )
8921 {
8922 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8923 }
8924 delete[] temp_tile;
8925 }
8926
8927
8928 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8929
8930 register_blank_tiles();
8931 register_used_tiles();
8932
8933 return 1;
8934
8935 }
8936 int32_t writetilefile(PACKFILE *f, int32_t index, int32_t count)
8937 {
8938 dword section_version=V_TILES;
8939 int32_t zversion = ZELDA_VERSION;
8940 int32_t zbuild = VERSION_BUILD;
8941
8942 if(!p_iputl(zversion,f))
8943 {
8944 return 0;
8945 }
8946 if(!p_iputl(zbuild,f))
8947 {
8948 return 0;
8949 }
8950 if(!p_iputw(section_version,f))
8951 {
8952 return 0;
8953 }
8954
8955 if(!write_deprecated_section_cversion(section_version,f))
8956 {
8957 return 0;
8958 }
8959
8960 //start tile id
8961 if(!p_iputl(index,f))
8962 {
8963 return 0;
8964 }
8965
8966 //count
8967 if(!p_iputl(count,f))
8968 {
8969 return 0;
8970 }
8971
8972 for ( int32_t tilect = 0; tilect < count; tilect++ )
8973 {
8974 if(!p_putc(newtilebuf[index+(tilect)].format,f))
8975 {
8976 return 0;
8977 }
8978 if(!pfwrite(newtilebuf[index+(tilect)].data,tilesize(newtilebuf[index+(tilect)].format),f))
8979 {
8980 return 0;
8981 }
8982 }
8983
8984 return 1;
8985
8986 }
8987
8988 static int32_t _selected_tile=-1, _selected_tcset=-1;
8989 int32_t select_tile(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
8990 {
8991 popup_zqdialog_start();
8992 reset_combo_animations();
8993 reset_combo_animations2();
8994 bound(tile,0,NEWMAXTILES-1);
8995 ex=exnow;
8996 int32_t done=0;
8997 int32_t oflip=flip;
8998 int32_t otile=tile;
8999 int32_t ocs=cs;
9000 int32_t first=(tile/TILES_PER_PAGE)*TILES_PER_PAGE; //first tile on the current page
9001 int32_t copy=-1;
9002 int32_t tile2=tile,copycnt=0;
9003 reftile = 0;
9004 int32_t tile_clicked=-1;
9005 bool rect_sel=true;
9006 bound(first,0,(TILES_PER_PAGE*TILE_PAGES)-1);
9007 position_mouse_z(0);
9008
9009 go();
9010
9011 register_used_tiles();
9012 int32_t w = 640;
9013 int32_t h = 480;
9014 int32_t window_xofs=(zq_screen_w-w-12)>>1;
9015 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
9016 int32_t screen_xofs=window_xofs+6;
9017 int32_t screen_yofs=window_yofs+25;
9018 int32_t panel_yofs=3;
9019 int32_t mul = 2;
9020 FONT *tfont = get_zc_font(font_lfont_l);
9021
9022 draw_tile_list_window();
9023 int32_t f=0;
9024 draw_tiles(first,cs,f);
9025
9026 if(type==0)
9027 {
9028 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
9029 }
9030 else
9031 {
9032 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
9033 }
9034
9035 go_tiles();
9036
9037 while(gui_mouse_b())
9038 {
9039 /* do nothing */
9040 rest(1);
9041 }
9042
9043 bool bdown=false;
9044
9045 #define FOREACH_START(_t) \
9046 { \
9047 int32_t _first, _last; \
9048 if(is_rect) \
9049 { \
9050 _first=top*TILES_PER_ROW+left; \
9051 _last=_first+rows*TILES_PER_ROW|+columns-1; \
9052 } \
9053 else \
9054 { \
9055 _first=zc_min(tile, tile2); \
9056 _last=zc_max(tile, tile2); \
9057 } \
9058 for(int32_t _t=_first; _t<=_last; _t++) \
9059 { \
9060 if(is_rect) \
9061 { \
9062 int32_t row=TILEROW(_t); \
9063 if(row<top || row>=top+rows) \
9064 continue; \
9065 int32_t col=TILECOL(_t); \
9066 if(col<left || col>=left+columns) \
9067 continue; \
9068 } \
9069
9070 #define FOREACH_END\
9071 } \
9072 }
9073
9074 bool did_snap = false;
9075 int otl = tile, otl2 = tile2;
9076 do
9077 {
9078 HANDLE_CLOSE_ZQDLG();
9079 if(exiting_program) break;
9080 rest(4);
9081 int32_t top=TILEROW(zc_min(tile, tile2));
9082 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
9083 int32_t rows=TILEROW(zc_max(tile, tile2))-top+1;
9084 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
9085 bool is_rect=(rows==1)||(columns==TILES_PER_ROW)||rect_sel;
9086 bool redraw=false;
9087
9088 if(mouse_z!=0)
9089 {
9090 sel_tile(tile,tile2,first,type,((mouse_z/abs(mouse_z))*(-1)*TILES_PER_PAGE));
9091 position_mouse_z(0);
9092 redraw=true;
9093 }
9094
9095 if(keypressed())
9096 {
9097 switch(readkey()>>8)
9098 {
9099 case KEY_ENTER_PAD:
9100 case KEY_ENTER:
9101 done=2;
9102 break;
9103
9104 case KEY_ESC:
9105 done=1;
9106 break;
9107
9108 case KEY_F1:
9109 onHelp();
9110 break;
9111
9112 case KEY_EQUALS:
9113 case KEY_PLUS_PAD:
9114 {
9115 if(CHECK_CTRL_CMD ||
9116 key[KEY_ALT] || key[KEY_ALTGR])
9117 {
9118 FOREACH_START(t)
9119 if(key[KEY_ALT] || key[KEY_ALTGR])
9120 shift_tile_colors(t, 16, false);
9121 else
9122 shift_tile_colors(t, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9123 FOREACH_END
9124
9125 register_blank_tiles();
9126 }
9127 else if(edit_cs)
9128 cs = (cs<13) ? cs+1:0;
9129
9130 redraw=true;
9131 break;
9132 }
9133
9134 case KEY_Z:
9135 case KEY_F12:
9136 {
9137 if(!did_snap)
9138 {
9139 //Export tile page as screenshot
9140 PALETTE temppal;
9141 get_palette(temppal);
9142 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
9143 draw_tiles(tempbmp,first,cs,f,false,true);
9144 save_bitmap(getSnapName(), tempbmp, RAMpal);
9145 destroy_bitmap(tempbmp);
9146
9147 redraw = true;
9148 did_snap = true;
9149 }
9150 break;
9151 }
9152
9153 case KEY_S:
9154 {
9155 if(!prompt_for_new_file_compat("Save ZTILE(.ztile)", "ztile", NULL,datapath,false))
9156 break;
9157 PACKFILE *f=pack_fopen_password(temppath,F_WRITE, "");
9158 if(!f) break;
9159 al_trace("Saving tile: %d\n", tile);
9160 writetilefile(f,tile,1);
9161 pack_fclose(f);
9162 break;
9163 }
9164 case KEY_L:
9165 {
9166 if(!prompt_for_existing_file_compat("Load ZTILE(.ztile)", "ztile", NULL,datapath,false))
9167 break;
9168 PACKFILE *f=pack_fopen_password(temppath,F_READ, "");
9169 if(!f) break;
9170 al_trace("Saving tile: %d\n", tile);
9171 if (!readtilefile(f))
9172 {
9173 al_trace("Could not read from .ztile packfile %s\n", temppath);
9174 jwin_alert("ZTILE File: Error","Could not load the specified Tile.",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9175 }
9176 else
9177 {
9178 jwin_alert("ZTILE File: Success!","Loaded the source tiles to your tile sheets!",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9179 }
9180
9181 pack_fclose(f);
9182 //register_blank_tiles();
9183 //register_used_tiles();
9184 redraw=true;
9185 break;
9186 }
9187 case KEY_MINUS:
9188 case KEY_MINUS_PAD:
9189 {
9190 if(CHECK_CTRL_CMD ||
9191 key[KEY_ALT] || key[KEY_ALTGR])
9192 {
9193 FOREACH_START(t)
9194 if(key[KEY_ALT] || key[KEY_ALTGR])
9195 shift_tile_colors(t, -16, false);
9196 else
9197 shift_tile_colors(t, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9198 FOREACH_END
9199
9200 register_blank_tiles();
9201 }
9202 else if(edit_cs)
9203 cs = (cs>0) ? cs-1:13;
9204
9205 redraw=true;
9206 break;
9207 }
9208
9209 case KEY_UP:
9210 {
9211 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9212 {
9213 case 3: //ALT and CTRL
9214 case 2: //ALT
9215 if(is_rect)
9216 {
9217 saved=false;
9218 go_slide_tiles(columns, rows, top, left);
9219 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9220 bool same = true;
9221
9222 for(int32_t d=0; d<columns; d++)
9223 {
9224 for(int32_t s=0; s<rows; s++)
9225 {
9226 int32_t t=((top+s)*TILES_PER_ROW)+left+d;
9227
9228 if(newtilebuf[t].format!=bitcheck) same = false;
9229 }
9230 }
9231
9232 if(!same) break;
9233
9234 // This used to do something. Too lazy to remove.
9235 // Can probably remove the above "same" check too.
9236 bitcheck = 2;
9237
9238 for(int32_t c=0; c<columns; c++)
9239 {
9240 for(int32_t r=0; r<rows; r++)
9241 {
9242 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9243 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(8*bitcheck));
9244 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data);
9245
9246 for(int32_t pixelrow=0; pixelrow<16*bitcheck; pixelrow++)
9247 {
9248 if(pixelrow==15*bitcheck)
9249 {
9250 int32_t srctile=temptile+TILES_PER_ROW;
9251 if(srctile>=NEWMAXTILES)
9252 srctile-=rows*TILES_PER_ROW;
9253 src_pixelrow=(qword*)(newtilebuf[srctile].data);
9254 }
9255
9256 *dest_pixelrow=*src_pixelrow;
9257 dest_pixelrow++;
9258 src_pixelrow++;
9259 }
9260 }
9261
9262 qword *dest_pixelrow=(qword*)(newtilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9263
9264 for(int32_t b=0; b<bitcheck; b++,dest_pixelrow++)
9265 {
9266 if((CHECK_CTRL_CMD))
9267 {
9268 *dest_pixelrow=0;
9269 }
9270 else
9271 {
9272 qword *src_pixelrow=(qword*)(newundotilebuf[(top*TILES_PER_ROW)+left+c].data+(8*b));
9273 *dest_pixelrow=*src_pixelrow;
9274 }
9275 }
9276 }
9277 }
9278
9279 register_blank_tiles();
9280 redraw=true;
9281 break;
9282
9283 case 1: //CTRL
9284 case 0: //None
9285 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(tile_page_row(tile)*TILES_PER_ROW):-TILES_PER_ROW);
9286 redraw=true;
9287
9288 default: //Others
9289 break;
9290 }
9291 }
9292 break;
9293
9294 case KEY_DOWN:
9295 {
9296 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9297 {
9298 case 3: //ALT and CTRL
9299 case 2: //ALT
9300 if(is_rect)
9301 {
9302 saved=false;
9303 go_slide_tiles(columns, rows, top, left);
9304 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9305 bool same = true;
9306
9307 for(int32_t c=0; c<columns; c++)
9308 {
9309 for(int32_t r=0; r<rows; r++)
9310 {
9311 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9312
9313 if(newtilebuf[t].format!=bitcheck) same = false;
9314 }
9315 }
9316
9317 if(!same) break;
9318
9319 // This used to do something. Too lazy to remove.
9320 // Can probably remove the above "same" check too.
9321 bitcheck = 2;
9322
9323 for(int32_t c=0; c<columns; c++)
9324 {
9325 for(int32_t r=rows-1; r>=0; r--)
9326 {
9327 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9328 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(112*bitcheck)+(8*(bitcheck-1)));
9329 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data+(120*bitcheck)+(8*(bitcheck-1)));
9330
9331 for(int32_t pixelrow=(8<<bitcheck)-1; pixelrow>=0; pixelrow--)
9332 {
9333 if(pixelrow<bitcheck)
9334 {
9335 int32_t srctile=temptile-TILES_PER_ROW;
9336 if(srctile<0)
9337 srctile+=rows*TILES_PER_ROW;
9338 qword *tempsrc=(qword*)(newtilebuf[srctile].data+(120*bitcheck)+(8*pixelrow));
9339 *dest_pixelrow=*tempsrc;
9340 //*dest_pixelrow=0;
9341 }
9342 else
9343 {
9344 *dest_pixelrow=*src_pixelrow;
9345 }
9346
9347 dest_pixelrow--;
9348 src_pixelrow--;
9349 }
9350 }
9351
9352 qword *dest_pixelrow=(qword*)(newtilebuf[(top*TILES_PER_ROW)+left+c].data);
9353 qword *src_pixelrow=(qword*)(newundotilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9354
9355 for(int32_t b=0; b<bitcheck; b++)
9356 {
9357 if((CHECK_CTRL_CMD))
9358 {
9359 *dest_pixelrow=0;
9360 }
9361 else
9362 {
9363 *dest_pixelrow=*src_pixelrow;
9364 }
9365
9366 dest_pixelrow++;
9367 src_pixelrow++;
9368 }
9369 }
9370 }
9371
9372 register_blank_tiles();
9373 redraw=true;
9374 break;
9375
9376 case 1: //CTRL
9377 case 0: //None
9378 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_ROWS_PER_PAGE-1)-tile_page_row(tile))*TILES_PER_ROW:TILES_PER_ROW);
9379 redraw=true;
9380
9381 default: //Others
9382 break;
9383 }
9384 }
9385 break;
9386
9387 case KEY_LEFT:
9388 {
9389 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9390 {
9391 case 3: //ALT and CTRL
9392 case 2: //ALT
9393 if(is_rect)
9394 {
9395 saved=false;
9396 go_slide_tiles(columns, rows, top, left);
9397 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9398 bool same = true;
9399
9400 for(int32_t c=0; c<columns; c++)
9401 {
9402 for(int32_t r=0; r<rows; r++)
9403 {
9404 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9405
9406 if(newtilebuf[t].format!=bitcheck) same = false;
9407 }
9408 }
9409
9410 if(!same) break;
9411
9412 // This used to do something. Too lazy to remove.
9413 // Can probably remove the above "same" check too.
9414 bitcheck = 2;
9415
9416 for(int32_t r=0; r<rows; r++)
9417 {
9418 for(int32_t c=0; c<columns; c++)
9419 {
9420 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9421 byte *dest_pixelrow=(newtilebuf[temptile].data);
9422
9423 for(int32_t pixelrow=0; pixelrow<16; pixelrow++)
9424 {
9425 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9426 {
9427 *dest_pixelrow=*(dest_pixelrow+1);
9428 dest_pixelrow++;
9429 }
9430
9431 if(c==columns-1)
9432 {
9433 if(!(CHECK_CTRL_CMD))
9434 {
9435 byte *tempsrc=(newundotilebuf[((top+r)*TILES_PER_ROW)+left].data+(pixelrow*8*bitcheck));
9436 *dest_pixelrow=*tempsrc;
9437 }
9438 }
9439 else
9440
9441 {
9442 byte *tempsrc=(newtilebuf[temptile+1].data+(pixelrow*8*bitcheck));
9443 *dest_pixelrow=*tempsrc;
9444 }
9445
9446 dest_pixelrow++;
9447 }
9448 }
9449 }
9450
9451 register_blank_tiles();
9452 redraw=true;
9453 }
9454
9455 break;
9456
9457 case 1: //CTRL
9458 case 0: //None
9459 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile%TILES_PER_ROW):-1);
9460 redraw=true;
9461
9462 default: //Others
9463 break;
9464 }
9465 }
9466 break;
9467
9468 case KEY_RIGHT:
9469 {
9470 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9471 {
9472 case 3: //ALT and CTRL
9473 case 2: //ALT
9474 if(is_rect)
9475 {
9476 saved=false;
9477 go_slide_tiles(columns, rows, top, left);
9478 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9479 bool same = true;
9480
9481 for(int32_t c=0; c<columns; c++)
9482 {
9483 for(int32_t r=0; r<rows; r++)
9484 {
9485 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9486
9487 if(newtilebuf[t].format!=bitcheck) same = false;
9488 }
9489 }
9490
9491 if(!same) break;
9492
9493 // This used to do something. Too lazy to remove.
9494 // Can probably remove the above "same" check too.
9495 bitcheck = 2;
9496
9497 for(int32_t r=0; r<rows; r++)
9498 {
9499 for(int32_t c=columns-1; c>=0; c--)
9500 {
9501 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9502 byte *dest_pixelrow=(newtilebuf[temptile].data)+(128*bitcheck)-1;
9503
9504 for(int32_t pixelrow=15; pixelrow>=0; pixelrow--)
9505 {
9506 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9507 {
9508 *dest_pixelrow=*(dest_pixelrow-1);
9509 dest_pixelrow--;
9510 }
9511
9512 if(c==0)
9513 {
9514 if(!(CHECK_CTRL_CMD))
9515 {
9516 byte *tempsrc=(newundotilebuf[(((top+r)*TILES_PER_ROW)+left+columns-1)].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9517 *dest_pixelrow=*tempsrc;
9518 }
9519 }
9520 else
9521 {
9522 byte *tempsrc=(newtilebuf[temptile-1].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9523 *dest_pixelrow=*tempsrc;
9524 }
9525
9526 dest_pixelrow--;
9527 }
9528 }
9529 }
9530
9531 register_blank_tiles();
9532 redraw=true;
9533 }
9534
9535 break;
9536
9537 case 1: //CTRL
9538 case 0: //None
9539 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILES_PER_ROW)-(tile%TILES_PER_ROW)-1:1);
9540 redraw=true;
9541
9542 default: //Others
9543 break;
9544 }
9545 }
9546 break;
9547
9548 case KEY_PGUP:
9549 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(TILEROW(tile)*TILES_PER_ROW):-TILES_PER_PAGE);
9550 redraw=true;
9551 break;
9552
9553 case KEY_PGDN:
9554 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_PAGES*TILE_ROWS_PER_PAGE)-TILEROW(tile)-1)*TILES_PER_ROW:TILES_PER_PAGE);
9555 redraw=true;
9556 break;
9557
9558 case KEY_HOME:
9559 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile):-(tile%TILES_PER_PAGE));
9560 redraw=true;
9561 break;
9562
9563 case KEY_END:
9564 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILE_PAGES)*(TILES_PER_PAGE)-tile-1:(TILES_PER_PAGE)-(tile%TILES_PER_PAGE)-1);
9565 redraw=true;
9566 break;
9567
9568 case KEY_P:
9569 {
9570 int32_t whatPage = gettilepagenumber("Goto Page", (PreFillTileEditorPage?(first/TILES_PER_PAGE):0));
9571
9572 if(whatPage >= 0)
9573 sel_tile(tile,tile2,first,type,((whatPage-TILEPAGE(tile))*TILE_ROWS_PER_PAGE)*TILES_PER_ROW);
9574
9575 break;
9576 }
9577
9578 case KEY_O:
9579 if(type==0 && copy>=0)
9580 {
9581 go_tiles();
9582
9583 if(key[KEY_LSHIFT] ||key[KEY_RSHIFT])
9584 {
9585 mass_overlay_tile(zc_min(tile,tile2),zc_max(tile,tile2),copy,cs,(CHECK_CTRL_CMD), rect_sel);
9586 saved=false;
9587 }
9588 else
9589 {
9590 saved = !overlay_tiles(tile,tile2,copy,copycnt,rect_sel,false,cs,(CHECK_CTRL_CMD));
9591 //overlay_tile(newtilebuf,tile,copy,cs,(CHECK_CTRL_CMD));
9592 }
9593
9594 saved=false;
9595 redraw=true;
9596 }
9597
9598 break;
9599
9600 case KEY_E:
9601 if(type==0)
9602 {
9603 edit_tile(tile,flip,cs);
9604 draw_tile_list_window();
9605 redraw=true;
9606 }
9607
9608 break;
9609
9610 case KEY_G:
9611 if(type==0)
9612 {
9613 grab_tile(tile,cs);
9614 draw_tile_list_window();
9615 redraw=true;
9616 }
9617
9618 break;
9619
9620 case KEY_C:
9621 copy=zc_min(tile,tile2);
9622 copycnt=abs(tile-tile2)+1;
9623 redraw=true;
9624 break;
9625
9626 case KEY_X:
9627 if(type==2)
9628 {
9629 ex=(ex+1)%3;
9630 }
9631
9632 break;
9633
9634 case KEY_R:
9635 if(type==2)
9636 break;
9637 if(type==1)
9638 {
9639 flip = rotate_value(flip);
9640 redraw=true;
9641 break;
9642 }
9643
9644 go_tiles();
9645
9646 if(CHECK_CTRL_CMD)
9647 {
9648 bool go=false;
9649 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
9650 go=true;
9651 else if(massRecolorSetup(cs))
9652 go=true;
9653
9654 if(go)
9655 {
9656 FOREACH_START(t)
9657 massRecolorApply(t);
9658 FOREACH_END
9659
9660 register_blank_tiles();
9661 }
9662 }
9663 else
9664 {
9665 FOREACH_START(t)
9666 rotate_tile(t,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
9667 FOREACH_END
9668 }
9669
9670 redraw=true;
9671 saved=false;
9672 break;
9673
9674 case KEY_SPACE:
9675 rect_sel=!rect_sel;
9676 copy=-1;
9677 redraw=true;
9678 break;
9679
9680 case KEY_H:
9681 flip^=1;
9682 go_tiles();
9683
9684 if(type==0)
9685 {
9686 normalize(tile,tile2,rect_sel,flip);
9687 flip=0;
9688 }
9689
9690 redraw=true;
9691 break;
9692
9693
9694 case KEY_V:
9695 if(copy==-1)
9696 {
9697 if(type!=2)
9698 {
9699 flip^=2;
9700 go_tiles();
9701
9702 if(type==0)
9703 {
9704 normalize(tile,tile2,rect_sel,flip);
9705 flip=0;
9706 }
9707 }
9708 }
9709 else
9710 {
9711 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9712 go_tiles();
9713 saved = !copy_tiles(tile,tile2,copy,copycnt,rect_sel,false);
9714 }
9715
9716 redraw=true;
9717 break;
9718
9719 case KEY_F:
9720 if(copy==-1)
9721 {
9722 break;
9723 }
9724 else
9725 {
9726 go_tiles();
9727 {
9728 saved = !copy_tiles_floodfill(tile,tile2,copy,copycnt,rect_sel,false);
9729 }
9730 }
9731
9732 redraw=true;
9733 break;
9734
9735 case KEY_DEL:
9736 if(type==0 && (key[KEY_LSHIFT]||key[KEY_RSHIFT]))
9737 {
9738 bool warn = (rect_sel
9739 && ((tile/20)!=(tile2/20))
9740 && !(tile%20==0&&tile2%20==19));
9741 int32_t z=zc_min(tile,tile2);
9742 int32_t count = abs(tile-tile2) + 1;
9743 tile=z;
9744 tile2=NEWMAXTILES;
9745 copy = tile + count;
9746 copycnt = NEWMAXTILES-copy;
9747 char buf[64];
9748
9749 if(count>1)
9750 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9751 else
9752 sprintf(buf,"Remove tile %d?",tile);
9753
9754 AlertDialog("Remove Tiles", std::string(buf)
9755 +"\nThis will offset the tiles that follow!"
9756 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9757 [&](bool ret,bool)
9758 {
9759 if(ret)
9760 {
9761 go_tiles();
9762 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9763 {
9764 redraw=true;
9765 saved=false;
9766 }
9767 }
9768 }).show();
9769 }
9770 delete_tiles(tile,tile2,rect_sel);
9771 redraw=true;
9772 break;
9773
9774 case KEY_U:
9775 {
9776 if(CHECK_CTRL_CMD)
9777 {
9778 //Only toggle the first 2 bits!
9779 show_only_unused_tiles = (show_only_unused_tiles&~3) | (((show_only_unused_tiles&3)+1)%4);
9780 }
9781 else
9782 {
9783 comeback_tiles();
9784 }
9785
9786 redraw=true;
9787 }
9788 break;
9789
9790 case KEY_8:
9791 case KEY_8_PAD:
9792 hide_8bit_marker();
9793 break;
9794
9795 case KEY_I: //insert tiles
9796 if(type==0)
9797 {
9798 bool warn = (rect_sel
9799 && ((tile/20)!=(tile2/20))
9800 && !(tile%20==0&&tile2%20==19));
9801 int32_t z=zc_min(tile,tile2);
9802 int32_t count = abs(tile-tile2) + 1;
9803 tile=z;
9804 tile2=NEWMAXTILES;
9805 copy = tile + count;
9806 copycnt = NEWMAXTILES-copy;
9807
9808 if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) //Remove
9809 {
9810 char buf[64];
9811
9812 if(count>1)
9813 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9814 else
9815 sprintf(buf,"Remove tile %d?",tile);
9816
9817 AlertDialog("Remove Tiles", std::string(buf)
9818 +"\nThis will offset the tiles that follow!"
9819 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9820 [&](bool ret,bool)
9821 {
9822 if(ret)
9823 {
9824 go_tiles();
9825 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9826 {
9827 redraw=true;
9828 saved=false;
9829 }
9830 }
9831 }).show();
9832 }
9833 else
9834 {
9835 char buf[64];
9836
9837 if(count>1)
9838 sprintf(buf,"Insert %d blank tiles?",count);
9839 else
9840 sprintf(buf,"Insert a blank tile?");
9841
9842 AlertDialog("Insert Tiles", std::string(buf)
9843 +"\nThis will offset the tiles that follow!"
9844 +(warn?"\nInserting tiles ignores rectangular selections!":""),
9845 [&](bool ret,bool)
9846 {
9847 if(ret)
9848 {
9849 go_tiles();
9850 if(copy_tiles(copy,tile2,tile,copycnt,false,true))
9851 {
9852 redraw=true;
9853 saved=false;
9854 }
9855 }
9856 }).show();
9857 }
9858
9859 copy=-1;
9860 tile2=tile=z;
9861 }
9862 break;
9863 case KEY_M:
9864 if(type==0)
9865 {
9866 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
9867 {
9868 go_tiles();
9869 if(copy_tiles(tile,tile2,copy,copycnt,rect_sel,true))
9870 saved=false;
9871 }
9872 else if(copy==-1)
9873 {
9874 // I don't know what this was supposed to be doing before.
9875 // It didn't work in anything like a sensible way.
9876 if(rect_sel)
9877 {
9878 make_combos_rect(top, left, rows, columns, cs);
9879 }
9880 else
9881 {
9882 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
9883 }
9884 }
9885
9886 redraw=true;
9887 }
9888 break;
9889
9890 case KEY_D:
9891 {
9892 int32_t frames=1;
9893 char buf[80];
9894 sprintf(buf, "%d", frames);
9895 create_relational_tiles_dlg[0].dp2=get_zc_font(font_lfont);
9896 create_relational_tiles_dlg[2].dp=buf;
9897
9898 large_dialog(create_relational_tiles_dlg);
9899
9900 int32_t ret=do_zqdialog(create_relational_tiles_dlg,2);
9901
9902 if(ret==5)
9903 {
9904 frames=zc_max(atoi(buf),1);
9905 bool same = true;
9906 int32_t bitcheck=newtilebuf[tile].format;
9907
9908 for(int32_t t=1; t<frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); ++t)
9909 {
9910 if(newtilebuf[tile+t].format!=bitcheck) same = false;
9911 }
9912
9913 if(!same)
9914 {
9915 jwin_alert("Error","The source tiles are not","in the same format.",NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9916 break;
9917 }
9918
9919 if(tile+(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96))>NEWMAXTILES)
9920 {
9921 jwin_alert("Error","Too many tiles will be created",NULL,NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9922 break;
9923 }
9924
9925 for(int32_t i=frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); i<(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96)); ++i)
9926 {
9927 reset_tile(newtilebuf, tile+i, bitcheck);
9928 }
9929
9930 if(create_relational_tiles_dlg[3].flags&D_SELECTED)
9931 {
9932 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9933 {
9934 for(int32_t j=0; j<frames; ++j)
9935 {
9936 merge_tiles(tile+(i*frames)+j, (tile+(relational_template[i][0]*frames)+j)<<2, ((tile+(relational_template[i][1]*frames)+j)<<2)+1, ((tile+(relational_template[i][2]*frames)+j)<<2)+2, ((tile+(relational_template[i][3]*frames)+j)<<2)+3);
9937 }
9938 }
9939 }
9940 else
9941 {
9942 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9943 {
9944 for(int32_t j=0; j<frames; ++j)
9945 {
9946 merge_tiles(tile+(i*frames)+j, (tile+(dungeon_carving_template[i][0]*frames)+j)<<2, ((tile+(dungeon_carving_template[i][1]*frames)+j)<<2)+1, ((tile+(dungeon_carving_template[i][2]*frames)+j)<<2)+2, ((tile+(dungeon_carving_template[i][3]*frames)+j)<<2)+3);
9947 }
9948 }
9949 }
9950 }
9951 register_blank_tiles();
9952 register_used_tiles();
9953 redraw=true;
9954 saved=false;
9955 break;
9956 }
9957
9958 case KEY_B:
9959 {
9960 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9961 bool control=(CHECK_CTRL_CMD);
9962 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9963 int format = control ? tf4Bit : tf8Bit;
9964
9965 do_convert_tile(tile, tile2, cs, rect_sel, format, shift, alt);
9966 register_blank_tiles();
9967 }
9968 break;
9969 }
9970
9971 clear_keybuf();
9972 }
9973
9974 if(!(key[KEY_Z] || key[KEY_F12]))
9975 did_snap = false;
9976
9977 if(gui_mouse_b()&1)
9978 {
9979 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
9980 {
9981 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
9982 {
9983 done=1;
9984 }
9985 }
9986
9987 int32_t x=gui_mouse_x()-screen_xofs;
9988 int32_t y=gui_mouse_y()-screen_yofs;
9989
9990 if(y>=0 && y<208*mul)
9991 {
9992 x=zc_min(zc_max(x,0),(320*mul)-1);
9993 int32_t t = (y>>(5))*TILES_PER_ROW + (x>>(5)) + first;
9994
9995 if(type==0 && (key[KEY_LSHIFT] || key[KEY_RSHIFT]))
9996 {
9997 tile2=t;
9998 }
9999 else
10000 {
10001 tile=tile2=t;
10002 }
10003
10004 if(tile_clicked!=t)
10005 {
10006 dclick_status=DCLICK_NOT;
10007 }
10008 else if(dclick_status == DCLICK_AGAIN)
10009 {
10010 while(gui_mouse_b())
10011 {
10012 /* do nothing */
10013 rest(1);
10014 }
10015
10016 if(((y>>(5))*TILES_PER_ROW + (x>>(5)) + first)!=t)
10017 {
10018 dclick_status=DCLICK_NOT;
10019 }
10020 else
10021 {
10022 if(type==0)
10023 {
10024 edit_tile(tile,flip,cs);
10025 draw_tile_list_window();
10026 redraw=true;
10027 }
10028 else
10029 {
10030 done=2;
10031 }
10032 }
10033 }
10034
10035 tile_clicked=t;
10036 }
10037 else if(x>300*mul && !bdown)
10038 {
10039 if(y<224*mul && first>0)
10040 {
10041 first-=TILES_PER_PAGE;
10042 redraw=true;
10043 }
10044
10045 if(y>=224*mul && first<TILES_PER_PAGE*(TILE_PAGES-1))
10046 {
10047 first+=TILES_PER_PAGE;
10048 redraw=true;
10049 }
10050
10051 bdown=true;
10052 }
10053
10054 if(type==1||type==2)
10055 {
10056 if(!bdown && isinRect(x,y,8*mul,216*mul+panel_yofs,23*mul,231*mul+panel_yofs))
10057 done=1;
10058
10059 if(!bdown && isinRect(x,y,148*mul,216*mul+panel_yofs,163*mul,231*mul+panel_yofs))
10060 done=2;
10061 }
10062 else if(!bdown && isinRect(x,y,127*mul,216*mul+panel_yofs,(127+15)*mul,(216+15)*mul+panel_yofs))
10063 {
10064 rect_sel=!rect_sel;
10065 copy=-1;
10066 redraw=true;
10067 }
10068 else if(!bdown && isinRect(x,y,150*mul,213*mul+panel_yofs,(150+28)*mul,(213+21)*mul+panel_yofs))
10069 {
10070 FONT *tf = font;
10071 font = tfont;
10072
10073 if(do_text_button(150*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Grab"))
10074 {
10075 font = tf;
10076 grab_tile(tile,cs);
10077 draw_tile_list_window();
10078 position_mouse_z(0);
10079 redraw=true;
10080 }
10081
10082 font = tf;
10083 }
10084 else if(!bdown && isinRect(x,y,(150+28)*mul,213*mul+panel_yofs,(150+28*2)*mul,(213+21)*mul+panel_yofs+21))
10085 {
10086 FONT *tf = font;
10087 font = tfont;
10088
10089 if(do_text_button((150+28)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Edit"))
10090 {
10091 font = tf;
10092 edit_tile(tile,flip,cs);
10093 draw_tile_list_window();
10094 redraw=true;
10095 }
10096
10097 font = tf;
10098 }
10099 else if(!bdown && isinRect(x,y,(150+28*2)*mul,213*mul+panel_yofs,(150+28*3)*mul,(213+21)*mul+panel_yofs))
10100 {
10101 FONT *tf = font;
10102 font = tfont;
10103
10104 if(do_text_button((150+28*2)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Export"))
10105 {
10106 std::string initial_path = "tileset.png";
10107 if (strlen(datapath))
10108 initial_path = fmt::format("{}/{}", datapath, initial_path);
10109 if(prompt_for_new_file_compat("Export Tile Page (.png)","png",NULL,initial_path,true))
10110 {
10111 PALETTE temppal;
10112 get_palette(temppal);
10113 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
10114 draw_tiles(tempbmp,first,cs,f,false,true);
10115 save_bitmap(temppath, tempbmp, RAMpal);
10116 destroy_bitmap(tempbmp);
10117 }
10118 }
10119
10120 font = tf;
10121 }
10122 else if(!bdown && isinRect(x,y,(150+28*3)*mul,213*mul+panel_yofs,(150+28*4)*mul,(213+21)*mul+panel_yofs))
10123 {
10124 FONT *tf = font;
10125 font = tfont;
10126
10127 if(do_text_button((150+28*3)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Recolor"))
10128 {
10129 if(massRecolorSetup(cs))
10130 {
10131 go_tiles();
10132
10133 FOREACH_START(t)
10134 massRecolorApply(t);
10135 FOREACH_END
10136
10137 register_blank_tiles();
10138 }
10139 }
10140
10141 font = tf;
10142 }
10143 else if(!bdown && isinRect(x,y,(150+28*4)*mul,213*mul+panel_yofs,(150+28*5)*mul,(213+21)*mul+panel_yofs))
10144 {
10145 FONT *tf = font;
10146 font = tfont;
10147
10148 if(do_text_button((150+28*4)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Done"))
10149 {
10150 done=1;
10151 }
10152
10153 font = tf;
10154 }
10155
10156 bdown=true;
10157 }
10158
10159 bool r_click = false;
10160
10161 if(gui_mouse_b()&2 && !bdown && type==0)
10162 {
10163 int32_t x=(gui_mouse_x()-screen_xofs);//&0xFF0;
10164 int32_t y=(gui_mouse_y()-screen_yofs);//&0xF0;
10165
10166 if(y>=0 && y<208*mul)
10167 {
10168 x=zc_min(zc_max(x,0),(320*mul)-1);
10169 int32_t t = ((y)>>(5))*TILES_PER_ROW + ((x)>>(5)) + first;
10170
10171 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
10172 tile=tile2=t;
10173 }
10174
10175 bdown = r_click = true;
10176 f=8;
10177 }
10178
10179 if(gui_mouse_b()==0)
10180 bdown=false;
10181
10182 position_mouse_z(0);
10183
10184 REDRAW:
10185
10186 if((f%8)==0 || InvalidBG == 1)
10187 redraw=true;
10188 if(otl != tile || otl2 != tile2)
10189 {
10190 otl = tile;
10191 otl2 = tile2;
10192 redraw = true;
10193 }
10194
10195 if(redraw)
10196 {
10197 draw_tiles(first,cs,f);
10198 }
10199 if(f&8)
10200 {
10201 if(rect_sel)
10202 {
10203 for(int32_t i=zc_min(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10204 zc_min(TILECOL(tile),TILECOL(tile2));
10205 i<=zc_max(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10206 zc_max(TILECOL(tile),TILECOL(tile2)); i++)
10207 {
10208 if(i>=first && i<first+TILES_PER_PAGE &&
10209 TILECOL(i)>=zc_min(TILECOL(tile),TILECOL(tile2)) &&
10210 TILECOL(i)<=zc_max(TILECOL(tile),TILECOL(tile2)))
10211 {
10212 int32_t x=TILECOL(i)<<(5);
10213 int32_t y=TILEROW(i-first)<<(5);
10214 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10215 }
10216 }
10217 }
10218 else
10219 {
10220 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
10221 {
10222 if(i>=first && i<first+TILES_PER_PAGE)
10223 {
10224 int32_t x=TILECOL(i)<<(5);
10225 int32_t y=TILEROW(i-first)<<(5);
10226 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10227 }
10228 }
10229 }
10230 }
10231
10232 if(type==0)
10233 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
10234 else
10235 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
10236
10237 if(type==2)
10238 {
10239 char cbuf[16];
10240 sprintf(cbuf, "E&xtend: %s",ex==2 ? "32x32" : ex==1 ? "32x16" : "16x16");
10241 gui_textout_ln(screen, get_zc_font(font_lfont_l), (uint8_t *)cbuf, (235*mul)+screen_xofs, (212*mul)+screen_yofs+panel_yofs, jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
10242 }
10243
10244 ++f;
10245
10246 if(r_click)
10247 {
10248 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_USED, HIDE_USED);
10249 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_UNUSED, HIDE_UNUSED);
10250 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_BLANK, HIDE_BLANK);
10251 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_8BIT, HIDE_8BIT_MARKER);
10252
10253 int current_tile_format = MENUID_SELTILE_COLOR_DEPTH_4_BIT;
10254 if (newtilebuf[tile].format == tf8Bit)
10255 current_tile_format = MENUID_SELTILE_COLOR_DEPTH_8_BIT;
10256 select_tile_color_depth_menu.select_only_uid(current_tile_format);
10257 select_tile_color_depth_cb = [&](int format){
10258 if (newtilebuf[tile].format == format)
10259 return;
10260
10261 bool skip_prompt = true;
10262 do_convert_tile(tile, tile2, cs, rect_sel, format, false, false, skip_prompt);
10263 };
10264
10265 NewMenu rcmenu
10266 {
10267 { "Copy", [&]()
10268 {
10269 copy = zc_min(tile,tile2);
10270 copycnt = abs(tile-tile2)+1;
10271 } },
10272 { "Paste", [&]()
10273 {
10274 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, false);
10275 if(saved) saved = !b;
10276 }, nullopt, copy < 0 },
10277 { "Move", [&]()
10278 {
10279 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, true);
10280 if(saved) saved = !b;
10281 }, nullopt, copy < 0 },
10282 { "Clear", [&]()
10283 {
10284 delete_tiles(tile, tile2, rect_sel);
10285 } },
10286 { "Set as Reference", [&]()
10287 {
10288 reftile = tile;
10289 } },
10290 {},
10291 { "Edit", [&]()
10292 {
10293 edit_tile(tile, flip, cs);
10294 draw_tile_list_window();
10295 } },
10296 { "Grab", [&]()
10297 {
10298 grab_tile(tile, cs);
10299 draw_tile_list_window();
10300 position_mouse_z(0);
10301 } },
10302 { "Scale", [&]()
10303 {
10304 bool b = scale_or_rotate_tiles(tile, tile2, cs, false);
10305 if(saved) saved = !b;
10306 }, nullopt, type != 0 },
10307 { "Angular Rotation", [&]()
10308 {
10309 bool b = scale_or_rotate_tiles(tile, tile2, cs, true);
10310 if(saved) saved = !b;
10311 }, nullopt, type != 0 },
10312 { "Color Depth", &select_tile_color_depth_menu },
10313 {},
10314 { "Blank?", [&]()
10315 {
10316 show_blank_tile(tile);
10317 } },
10318 {},
10319 { "View ", &select_tile_view_menu },
10320 { "Overlay", [&]()
10321 {
10322 overlay_tile(newtilebuf, tile, copy, cs, 0);
10323 } },
10324 { "H-Flip", [&]()
10325 {
10326 flip ^= 1;
10327 go_tiles();
10328
10329 if(type == 0)
10330 {
10331 normalize(tile, tile2, rect_sel, flip);
10332 flip = 0;
10333 }
10334 } },
10335 { "V-Flip", [&]()
10336 {
10337 flip ^= 2;
10338 go_tiles();
10339
10340 if(type == 0)
10341 {
10342 normalize(tile, tile2, rect_sel, flip);
10343 flip = 0;
10344 }
10345 } },
10346 { "Create Combos", [&]()
10347 {
10348 if(rect_sel)
10349 make_combos_rect(top, left, rows, columns, cs);
10350 else
10351 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
10352 }, nullopt, type != 0 },
10353 { "Insert", [&]()
10354 {
10355 bool warn = (rect_sel
10356 && ((tile/20)!=(tile2/20))
10357 && !(tile%20==0&&tile2%20==19));
10358 int32_t z = zc_min(tile, tile2);
10359 int32_t count = abs(tile-tile2) + 1;
10360 tile = z;
10361 tile2 = NEWMAXTILES;
10362 copy = tile + count;
10363 copycnt = NEWMAXTILES-copy;
10364
10365 string msg;
10366
10367 if(count>1)
10368 msg = fmt::format("Insert {} blank tiles?",count);
10369 else
10370 msg = "Insert a blank tile?";
10371
10372 AlertDialog("Insert Tiles", msg
10373 +"\nThis will offset the tiles that follow!"
10374 +(warn?"\nInserting tiles ignores rectangular selections!":""),
10375 [&](bool ret,bool)
10376 {
10377 if(ret)
10378 {
10379 go_tiles();
10380 if(copy_tiles(copy, tile2, tile, copycnt, false, true))
10381 saved = false;
10382 }
10383 }).show();
10384
10385 copy=-1;
10386 tile2=tile=z;
10387 }, nullopt, type != 0 },
10388 { "Remove", [&]()
10389 {
10390 bool warn = (rect_sel
10391 && ((tile/20)!=(tile2/20))
10392 && !(tile%20==0&&tile2%20==19));
10393 int32_t z = zc_min(tile, tile2);
10394 int32_t count = abs(tile-tile2) + 1;
10395 tile = z;
10396 tile2 = NEWMAXTILES;
10397 copy = tile + count;
10398 copycnt = NEWMAXTILES-copy;
10399
10400 string msg;
10401
10402 if(count>1)
10403 msg = fmt::format("Remove tiles {} - {}?", tile, copy-1);
10404 else
10405 msg = fmt::format("Remove tile {}?", tile);
10406
10407 AlertDialog("Remove Tiles", msg
10408 +"\nThis will offset the tiles that follow!"
10409 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
10410 [&](bool ret,bool)
10411 {
10412 if(ret)
10413 {
10414 go_tiles();
10415 if(copy_tiles(tile, tile2, copy, copycnt, false, true))
10416 saved = false;
10417 }
10418 }).show();
10419
10420 copy=-1;
10421 tile2=tile=z;
10422 }, nullopt, type != 0 },
10423 };
10424 rcmenu.pop(window_mouse_x(),window_mouse_y());
10425 redraw = true;
10426 r_click = false;
10427 goto REDRAW;
10428 }
10429 update_hw_screen();
10430 }
10431 while(!done);
10432
10433 while(gui_mouse_b())
10434 {
10435 /* do nothing */
10436 rest(1);
10437 }
10438
10439 comeback();
10440 register_blank_tiles();
10441 register_used_tiles();
10442 setup_combo_animations();
10443 setup_combo_animations2();
10444 int32_t ret = done-1;
10445 if(ret)
10446 {
10447 _selected_tile = tile;
10448 _selected_tcset = cs;
10449 }
10450
10451 popup_zqdialog_end();
10452 return ret;
10453 }
10454 int32_t select_tile_2(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
10455 {
10456 if(_selected_tile > -1)
10457 {
10458 tile = _selected_tile;
10459 cs = _selected_tcset;
10460 }
10461 int32_t ret = select_tile(tile,flip,type,cs,edit_cs,exnow,always_use_flip);
10462 if(_selected_tile < 0)
10463 {
10464 _selected_tile = tile;
10465 _selected_tcset = cs;
10466 }
10467 return ret;
10468 }
10469
10470 int32_t onTiles()
10471 {
10472 return onGotoTiles(-1);
10473 }
10474
10475 int32_t onGotoTiles(int32_t startfrom)
10476 {
10477 static int32_t t = 0;
10478 if (startfrom > -1)
10479 t = startfrom;
10480 int32_t f = 0;
10481 int32_t c = CSet;
10482 reset_pal_cycling();
10483 // loadlvlpal(Map.CurrScr()->color);
10484 rebuild_trans_table();
10485 select_tile(t, f, 0, c, true);
10486 refresh(rALL);
10487 return D_O_K;
10488 }
10489
10490 int32_t combopage_animate = 1;
10491 void draw_combo(BITMAP *dest, int x,int y,int c,int cs,bool animate)
10492 {
10493 if(unsigned(c)<MAXCOMBOS)
10494 {
10495 newcombo& cmb = combobuf[c];
10496 int t = cmb.tile;
10497 if(!animate)
10498 cmb.tile = cmb.o_tile;
10499 put_combo(dest,x,y,c,cs,0,0);
10500 cmb.tile = t;
10501 }
10502 else
10503 {
10504 rectfill(dest,x,y,x+32-1,y+32-1,0);
10505 }
10506 }
10507
10508 void draw_combos(int32_t page,int32_t cs,bool cols)
10509 {
10510 clear_bitmap(screen2);
10511 BITMAP *buf = create_bitmap_ex(8,16,16);
10512
10513 int32_t w = 32;
10514 int32_t h = 32;
10515 int32_t mul = 2;
10516
10517 int32_t window_xofs=(zq_screen_w-640-12)>>1;
10518 int32_t window_yofs=(zq_screen_h-480-25-6)>>1;
10519 int32_t screen_xofs=window_xofs+6;
10520 int32_t screen_yofs=window_yofs+25;
10521
10522 if(cols==false)
10523 {
10524 for(int32_t i=0; i<256; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
10525 {
10526 int32_t x = (i%COMBOS_PER_ROW)*w;
10527 int32_t y = (i/COMBOS_PER_ROW)*h;
10528
10529 combotile_override_x = x+screen_xofs+(w-16)/2;
10530 combotile_override_y = y+screen_yofs+(h-16)/2;
10531 draw_combo(buf,0,0,i+(page<<8),cs,combopage_animate);
10532 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10533 }
10534 }
10535 else
10536 {
10537 int32_t c = 0;
10538
10539 for(int32_t i=0; i<256; i++)
10540 {
10541 int32_t x = (i%COMBOS_PER_ROW)*w;
10542 int32_t y = (i/COMBOS_PER_ROW)*h;
10543
10544 combotile_override_x = x+screen_xofs+(w-16)/2;
10545 combotile_override_y = y+screen_yofs+(h-16)/2;
10546 draw_combo(buf,0,0,c+(page<<8),cs,combopage_animate);
10547 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10548 ++c;
10549
10550 if((i&3)==3)
10551 c+=48;
10552
10553 if((i%COMBOS_PER_ROW)==(COMBOS_PER_ROW-1))
10554 c-=256;
10555 }
10556 }
10557 combotile_override_x = combotile_override_y = -1;
10558
10559 for(int32_t x=(64*mul); x<(320*mul); x+=(64*mul))
10560 {
10561 vline(screen2,x,0,(208*mul)-1,vc(15));
10562 }
10563
10564 destroy_bitmap(buf);
10565 }
10566
10567 void combo_info(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,int32_t buttons)
10568 {
10569 int32_t yofs=3;
10570 static BITMAP *buf = create_bitmap_ex(8,16,16);
10571 int32_t mul = 2;
10572 FONT *tfont = get_zc_font(font_lfont_l);
10573
10574 rectfill(screen2,0,210*2,(320*2)-1,(240*2)-1,jwin_pal[jcBOX]);
10575 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
10576 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
10577
10578 jwin_draw_frame(screen2,(31*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10579
10580 if(copy>=0)
10581 {
10582 put_combo(buf,0,0,copy,cs,0,0);
10583 stretch_blit(buf,screen2,0,0,16,16,31*mul,216*mul+yofs,16*mul,16*mul);
10584
10585 if(copycnt>1)
10586 {
10587 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
10588 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
10589 }
10590 else
10591 {
10592 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
10593 }
10594 }
10595 else
10596 {
10597 if (InvalidBG == 2)
10598 {
10599 draw_checkerboard(screen2, 31 * mul, 216 * mul + yofs, 16 * mul);
10600 }
10601 else if(InvalidBG == 1)
10602 {
10603 for(int32_t dy=0; dy<16*mul; dy++)
10604 {
10605 for(int32_t dx=0; dx<16*mul; dx++)
10606 {
10607 screen2->line[(216*mul)+yofs+dy][(31*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10608 }
10609 }
10610 }
10611 else
10612 {
10613 rectfill(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(0));
10614 rect(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10615 line(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10616 line(screen2, (31*mul), (216*mul)+yofs+31, (31*mul)+31, (216*mul)+yofs, vc(15));
10617 }
10618 }
10619
10620 jwin_draw_frame(screen2,(53*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10621 put_combo(buf,0,0,tile,cs,0,0);
10622 stretch_blit(buf,screen2,0,0,16,16,53*mul,216*mul+yofs,16*mul,16*mul);
10623
10624 if(tile>tile2)
10625 {
10626 zc_swap(tile,tile2);
10627 }
10628
10629 char cbuf[8];
10630 cbuf[0]=0;
10631
10632 if(tile2!=tile)
10633 {
10634 sprintf(cbuf,"-%d",tile2);
10635 }
10636
10637 textprintf_ex(screen2,tfont,(73*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"combo: CSet %d", cs);
10638 textprintf_ex(screen2,tfont,(73*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,cbuf);
10639
10640 if(tile2==tile)
10641 {
10642 int32_t nextcombo=combobuf[tile].nextcombo;
10643 int32_t nextcset=(combobuf[tile].animflags & AF_CYCLENOCSET) ? cs : combobuf[tile].nextcset;
10644 jwin_draw_frame(screen2,(136*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10645
10646 if(nextcombo>0 && !(combobuf[tile].animflags & AF_CYCLEUNDERCOMBO))
10647 {
10648 put_combo(buf,0,0,nextcombo,nextcset,0,0);
10649 stretch_blit(buf,screen2,0,0,16,16,136*mul,216*mul+yofs,16*mul,16*mul);
10650 }
10651 else
10652 {
10653 if (InvalidBG == 2)
10654 {
10655 draw_checkerboard(screen2, 136 * mul, 216 * mul + yofs, 16 * mul);
10656 }
10657 else if(InvalidBG == 1)
10658 {
10659 for(int32_t dy=0; dy<16*mul; dy++)
10660 {
10661 for(int32_t dx=0; dx<16*mul; dx++)
10662 {
10663 screen2->line[(216*mul)+yofs+dy][(136*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10664 }
10665 }
10666 }
10667 else
10668 {
10669 rectfill(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(0));
10670 rect(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10671 line(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10672 line(screen2, (136*mul), (216*mul)+yofs+31, (136*mul)+31, (216*mul)+yofs, vc(15));
10673 }
10674 }
10675
10676 textprintf_right_ex(screen2,tfont,(132*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Cycle:");
10677 textprintf_right_ex(screen2,tfont,(132*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",nextcombo);
10678 }
10679
10680
10681 FONT *tf = font;
10682 font = tfont;
10683
10684 draw_checkbox(screen2,320,440+yofs,16,combopage_animate);
10685 textprintf_ex(screen2,tfont,320+18,440+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Animate");
10686
10687 if(buttons&2)
10688 {
10689 draw_text_button(screen2,404,426+yofs,88,42,"Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10690 }
10691
10692 if(buttons&4)
10693 {
10694 draw_text_button(screen2,494,426+yofs,88,42,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10695 }
10696
10697 font = tf;
10698
10699 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
10700 textprintf_ex(screen2,tfont,(293*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
10701 textprintf_centre_ex(screen2,tfont,(309*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
10702 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
10703
10704 int32_t w = 640;
10705 int32_t h = 480;
10706 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10707 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10708 int32_t screen_xofs=window_xofs+6;
10709 int32_t screen_yofs=window_yofs+25;
10710
10711 custom_vsync();
10712 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
10713 SCRFIX();
10714 //destroy_bitmap(buf);
10715 }
10716
10717 void sel_combo(int32_t &tile, int32_t &tile2, int32_t s, bool cols)
10718 {
10719 int32_t page = tile&0xFF00;
10720 tile &= 0xFF;
10721
10722 if(!cols)
10723 tile += s;
10724 else
10725 {
10726 if(s==-COMBOS_PER_ROW)
10727 tile-=4;
10728
10729 if(s==COMBOS_PER_ROW)
10730 tile+=4;
10731
10732 if(s==-1)
10733 tile-=1;
10734
10735 if(s==1)
10736 tile+=1;
10737 }
10738
10739 /*
10740 if(s==1)
10741 {
10742 if((tile&3)==3)
10743 tile+=48;
10744 else
10745 ++tile;
10746 }
10747 if(s==-1)
10748 {
10749 if((tile&3)==0)
10750 tile-=48;
10751 else
10752 --tile;
10753 }
10754 }
10755 */
10756 bound(tile,0,255);
10757 tile += page;
10758
10759 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
10760 tile2 = tile;
10761 }
10762
10763 void draw_combo_list_window()
10764 {
10765 int32_t window_xofs=0;
10766 int32_t window_yofs=0;
10767 int32_t w = 640;
10768 int32_t h = 480;
10769
10770 window_xofs=(zq_screen_w-w-12)>>1;
10771 window_yofs=(zq_screen_h-h-25-6)>>1;
10772 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
10773 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
10774 FONT *oldfont = font;
10775 font = get_zc_font(font_lfont);
10776 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Combo", true);
10777 font=oldfont;
10778 }
10779
10780
10781 static int32_t _selected_combo=-1, _selected_cset=-1;
10782 bool select_combo_2(int32_t &cmb,int32_t &cs)
10783 {
10784 popup_zqdialog_start();
10785 reset_combo_animations();
10786 reset_combo_animations2();
10787 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
10788 // static int32_t cmb=0;
10789 int32_t page=cmb>>8;
10790 int32_t tile2=cmb;
10791 int32_t done=0;
10792 int32_t tile_clicked=-1;
10793 int32_t t2;
10794 int32_t copy=-1;
10795 int32_t copycnt=0;
10796
10797 position_mouse_z(0);
10798
10799 go();
10800 int32_t w = 640;
10801 int32_t h = 480;
10802 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10803 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10804 int32_t screen_xofs=window_xofs+6;
10805 int32_t screen_yofs=window_yofs+25;
10806 int32_t panel_yofs=3;
10807 int32_t mul = 2;
10808 FONT *tfont = get_zc_font(font_lfont_l);
10809
10810 draw_combo_list_window();
10811 draw_combos(page,cs,true);
10812 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
10813
10814 while(gui_mouse_b())
10815 {
10816 /* do nothing */
10817 rest(1);
10818 }
10819
10820 bool bdown=false;
10821 int32_t f=0;
10822 int otl = cmb, otl2 = tile2;
10823
10824 do
10825 {
10826 HANDLE_CLOSE_ZQDLG();
10827 if(exiting_program) break;
10828 rest(4);
10829 bool redraw=false;
10830
10831 if(mouse_z<0)
10832 {
10833 if(page<COMBO_PAGES-1)
10834 {
10835 ++page;
10836 cmb=tile2=(page<<8)+(cmb&0xFF);
10837 }
10838
10839 position_mouse_z(0);
10840 redraw=true;
10841 }
10842 else if(mouse_z>0)
10843 {
10844 if(page>0)
10845 {
10846 --page;
10847 cmb=tile2=(page<<8)+(cmb&0xFF);
10848 }
10849
10850 position_mouse_z(0);
10851 redraw=true;
10852 }
10853
10854 if(keypressed())
10855 {
10856 switch(readkey()>>8)
10857 {
10858 case KEY_DEL:
10859 cmb=0;
10860 done=2;
10861 break;
10862
10863 case KEY_ENTER_PAD:
10864 case KEY_ENTER:
10865 done=2;
10866 break;
10867
10868 case KEY_ESC:
10869 done=1;
10870 break;
10871
10872 case KEY_F1:
10873 onHelp();
10874 break;
10875
10876 case KEY_EQUALS:
10877 case KEY_PLUS_PAD:
10878 cs = (cs<13) ? cs+1:0;
10879 redraw=true;
10880 break;
10881
10882 case KEY_MINUS:
10883 case KEY_MINUS_PAD:
10884 cs = (cs>0) ? cs-1:13;
10885 redraw=true;
10886 break;
10887
10888 case KEY_UP:
10889 sel_combo(cmb,tile2,-COMBOS_PER_ROW,true);
10890 redraw=true;
10891 break;
10892
10893 case KEY_DOWN:
10894 sel_combo(cmb,tile2,COMBOS_PER_ROW,true);
10895 redraw=true;
10896 break;
10897
10898 case KEY_LEFT:
10899 sel_combo(cmb,tile2,-1,true);
10900 redraw=true;
10901 break;
10902
10903 case KEY_RIGHT:
10904 sel_combo(cmb,tile2,1,true);
10905 redraw=true;
10906 break;
10907
10908 case KEY_PGUP:
10909 if(page>0)
10910 {
10911 --page;
10912 cmb=tile2=(page<<8)+(cmb&0xFF);
10913 }
10914
10915 redraw=true;
10916 break;
10917
10918 case KEY_PGDN:
10919 if(page<COMBO_PAGES-1)
10920 {
10921 ++page;
10922 cmb=tile2=(page<<8)+(cmb&0xFF);
10923 }
10924
10925 redraw=true;
10926 break;
10927
10928 case KEY_P:
10929 {
10930 int32_t choosepage=getnumber("Goto Page", (PreFillComboEditorPage?page:0));
10931
10932 if(!cancelgetnum)
10933 page=(zc_min(choosepage,COMBO_PAGES-1));
10934
10935 cmb=tile2=(page<<8)+(cmb&0xFF);
10936 redraw=true;
10937 break;
10938 }
10939 }
10940
10941 clear_keybuf();
10942 }
10943
10944 if(gui_mouse_b()&1)
10945 {
10946 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
10947 {
10948 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
10949 {
10950 done=1;
10951 }
10952 }
10953
10954 int32_t x=gui_mouse_x()-screen_xofs;
10955 int32_t y=gui_mouse_y()-screen_yofs;
10956
10957 if(y>=0 && y<208*mul)
10958 {
10959 x=zc_min(zc_max(x,0),(320*mul)-1);
10960 int32_t t;
10961
10962 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10963
10964 bound(t,0,255);
10965 t+=page<<8;
10966 cmb=tile2=t;
10967
10968 if(tile_clicked!=t)
10969 {
10970 dclick_status=DCLICK_NOT;
10971 }
10972 else if(dclick_status == DCLICK_AGAIN)
10973 {
10974 while(gui_mouse_b())
10975 {
10976 /* do nothing */
10977 }
10978
10979 t2 = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10980
10981 if(t2!=t)
10982 {
10983 dclick_status=DCLICK_NOT;
10984 }
10985 else
10986 {
10987 done=2;
10988 }
10989 }
10990
10991 tile_clicked=t;
10992 }
10993 else if(y>=(208*mul) && x>(300*mul) && !bdown)
10994 {
10995 if(y<(224*mul)+panel_yofs && page>0)
10996 {
10997 --page;
10998 redraw=true;
10999 }
11000
11001 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
11002 {
11003 ++page;
11004 redraw=true;
11005 }
11006
11007 bdown=true;
11008 }
11009
11010 if(!bdown && isinRect(x,y,(247*mul),(213*mul),((247+44)*mul),((213+21)*mul)))
11011 {
11012 FONT *tf = font;
11013 font = tfont;
11014
11015 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11016 {
11017 done=2;
11018 }
11019
11020 font = tf;
11021 }
11022 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11023 {
11024 FONT *tf = font;
11025 font = tfont;
11026
11027 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11028 combopage_animate = combopage_animate ? 0 : 1;
11029 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11030 redraw = true;
11031
11032 font = tf;
11033 }
11034
11035 bdown=true;
11036 }
11037
11038 bool r_click = false;
11039
11040 if(gui_mouse_b()&2 && !bdown)
11041 {
11042 int32_t x=gui_mouse_x()+screen_xofs;
11043 int32_t y=gui_mouse_y()+screen_yofs;
11044
11045 if(y>=0 && y<208*mul)
11046 {
11047 x=zc_min(zc_max(x,0),(320*mul)-1);
11048 int32_t t;
11049
11050 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11051
11052 bound(t,0,255);
11053 t+=page<<8;
11054
11055 if(t<zc_min(cmb,tile2) || t>zc_max(cmb,tile2))
11056 cmb=tile2=t;
11057 }
11058
11059 bdown = r_click = true;
11060 f=8;
11061 }
11062
11063 if(gui_mouse_b()==0)
11064 bdown=false;
11065
11066 if((f%8) || InvalidBG == 1)
11067 redraw = true;
11068 if(otl != cmb || otl2 != tile2)
11069 {
11070 otl = cmb;
11071 otl2 = tile2;
11072 redraw = true;
11073 }
11074
11075 if(redraw || combopage_animate)
11076 draw_combos(page,cs,true);
11077
11078 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
11079
11080 if(f&8)
11081 {
11082 int32_t x,y;
11083
11084 for(int32_t i=zc_min(cmb,tile2); i<=zc_max(cmb,tile2); i++)
11085 {
11086 if((i>>8)==page)
11087 {
11088 int32_t t=i&255;
11089
11090 x=((t&3) + ((t/52)<<2)) << 5;
11091 y=((t%52)>>2) << 5;
11092
11093 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11094 }
11095 }
11096
11097 SCRFIX();
11098 }
11099
11100 ++f;
11101
11102 }
11103 while(!done);
11104
11105 while(gui_mouse_b())
11106 {
11107 /* do nothing */
11108 rest(1);
11109 }
11110
11111 comeback();
11112 setup_combo_animations();
11113 setup_combo_animations2();
11114
11115 bool ret = done==2;
11116 if(ret)
11117 {
11118 _selected_combo = cmb;
11119 _selected_cset = cs;
11120 }
11121
11122 popup_zqdialog_end();
11123 return ret;
11124 }
11125
11126 bool select_combo_3(int32_t &cmb,int32_t &cs)
11127 {
11128 if(_selected_combo < 0)
11129 {
11130 _selected_combo = Combo;
11131 _selected_cset = CSet;
11132 }
11133 cmb = _selected_combo;
11134 cs = _selected_cset;
11135 return select_combo_2(cmb,cs);
11136 }
11137
11138 bool advpaste(int32_t tile, int32_t tile2, int32_t copy)
11139 {
11140 static bitstring pasteflags;
11141 static const vector<CheckListInfo> advp_names =
11142 {
11143 { "Tile" },
11144 { "CSet2" },
11145 { "Solidity" },
11146 { "Animation" },
11147 { "Type" },
11148 { "Inherent Flag" },
11149 { "Attribytes" },
11150 { "Attrishorts" },
11151 { "Attributes" },
11152 { "Flags", "The 16 Flags on the 'Flags' tab" },
11153 { "Gen. Flags", "The 2 'General Flags' on the 'Flags' tab" },
11154 { "Label" },
11155 { "Script" },
11156 { "Effect" },
11157 { "Triggers Tab" },
11158 { "Lifting Tab" },
11159 { "Gen: Movespeed", "The Movespeed related values from the 'General' tab" },
11160 { "Gen: SFX", "The SFX related values from the 'General' tab" },
11161 { "Gen: Sprites", "The Sprites related values from the 'General' tab" },
11162 };
11163 if(!call_checklist_dialog("Advanced Paste",advp_names,pasteflags))
11164 return false;
11165
11166 //Paste to each combo in the range
11167 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11168 {
11169 combobuf[i].advpaste(combobuf[copy], pasteflags);
11170 }
11171
11172 if(pasteflags.get(CMB_ADVP_TILE)) //reset animations if needed
11173 {
11174 setup_combo_animations();
11175 setup_combo_animations2();
11176 }
11177
11178 return true;
11179 }
11180
11181 int32_t combo_screen(int32_t pg, int32_t tl)
11182 {
11183 popup_zqdialog_start();
11184 reset_combo_animations();
11185 reset_combo_animations2();
11186 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
11187 static int32_t tile=0;
11188 static int32_t page=0;
11189
11190 if(pg>-1)
11191 page = pg;
11192
11193 if(tl>-1)
11194 tile = tl;
11195
11196 int32_t tile2=tile;
11197 int32_t done=0;
11198 int32_t cs = CSet;
11199 int32_t copy=-1;
11200 int32_t copycnt=0;
11201
11202 int32_t tile_clicked=-1;
11203 int32_t t2;
11204
11205 bool masscopy;
11206
11207 go();
11208 int32_t w = 640;
11209 int32_t h = 480;
11210 int32_t window_xofs=(zq_screen_w-w-12)>>1;
11211 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
11212 int32_t screen_xofs=window_xofs+6;
11213 int32_t screen_yofs=window_yofs+25;
11214 int32_t panel_yofs=3;
11215 int32_t mul = 2;
11216 FONT *tfont = get_zc_font(font_lfont_l);
11217
11218 draw_combo_list_window();
11219 draw_combos(page,cs,true);
11220 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11221 go_combos();
11222 position_mouse_z(0);
11223
11224 while(gui_mouse_b())
11225 {
11226 /* do nothing */
11227 }
11228
11229 bool bdown=false;
11230 int32_t f=0;
11231 int otl = tile, otl2 = tile2;
11232
11233 do
11234 {
11235 HANDLE_CLOSE_ZQDLG();
11236 if(exiting_program) break;
11237 rest(4);
11238 bool redraw=false;
11239
11240 if(mouse_z<0)
11241 {
11242 if(page<COMBO_PAGES-1)
11243 {
11244 ++page;
11245 tile=tile2=(page<<8)+(tile&0xFF);
11246 }
11247
11248 position_mouse_z(0);
11249 redraw=true;
11250 }
11251 else if(mouse_z>0)
11252 {
11253 if(page>0)
11254 {
11255 --page;
11256 tile=tile2=(page<<8)+(tile&0xFF);
11257 }
11258
11259 position_mouse_z(0);
11260 redraw=true;
11261 }
11262
11263 if(keypressed())
11264 {
11265 switch(readkey()>>8)
11266 {
11267 case KEY_ENTER_PAD:
11268 case KEY_ENTER:
11269 done=2;
11270 break;
11271
11272 case KEY_ESC:
11273 done=1;
11274 break;
11275
11276 case KEY_F1:
11277 onHelp();
11278 break;
11279
11280 case KEY_EQUALS:
11281 case KEY_PLUS_PAD:
11282 if(CHECK_CTRL_CMD)
11283 {
11284 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11285 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11286 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11287
11288 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11289 {
11290 combobuf[i].set_tile(wrap(combobuf[i].o_tile + amnt,
11291 0, NEWMAXTILES-1));
11292 }
11293
11294 setup_combo_animations();
11295 redraw=true;
11296 }
11297 else
11298 {
11299 cs = (cs<13) ? cs+1:0;
11300 redraw=true;
11301 }
11302
11303 break;
11304
11305 case KEY_MINUS:
11306 case KEY_MINUS_PAD:
11307 if(CHECK_CTRL_CMD)
11308 {
11309 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11310 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11311 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11312
11313 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11314 {
11315 combobuf[i].set_tile(wrap(combobuf[i].o_tile - amnt,
11316 0, NEWMAXTILES-1));
11317 }
11318
11319 setup_combo_animations();
11320 redraw=true;
11321 }
11322 else
11323 {
11324 cs = (cs>0) ? cs-1:13;
11325 redraw=true;
11326 }
11327
11328 break;
11329
11330 case KEY_UP:
11331 sel_combo(tile,tile2,-COMBOS_PER_ROW,true);
11332 redraw=true;
11333 break;
11334
11335 case KEY_DOWN:
11336 sel_combo(tile,tile2,COMBOS_PER_ROW,true);
11337 redraw=true;
11338 break;
11339
11340 case KEY_LEFT:
11341 sel_combo(tile,tile2,-1,true);
11342 redraw=true;
11343 break;
11344
11345 case KEY_RIGHT:
11346 sel_combo(tile,tile2,1,true);
11347 redraw=true;
11348 break;
11349
11350 case KEY_PGUP:
11351 if(page>0)
11352 {
11353 --page;
11354 tile=tile2=(page<<8)+(tile&0xFF);
11355 }
11356
11357 redraw=true;
11358 break;
11359
11360 case KEY_PGDN:
11361 if(page<COMBO_PAGES-1)
11362 {
11363 ++page;
11364 tile=tile2=(page<<8)+(tile&0xFF);
11365 }
11366
11367 redraw=true;
11368 break;
11369
11370 case KEY_A:
11371 {
11372 tile=(page<<8);
11373 tile2=(page<<8)+(0xFF);
11374 }
11375
11376 redraw=true;
11377 break;
11378
11379 case KEY_P:
11380 {
11381 int32_t choosepage = getnumber("Goto Page", (PreFillComboEditorPage?page:0));
11382
11383 if(!cancelgetnum)
11384 page=(zc_min(choosepage,COMBO_PAGES-1));
11385
11386 tile=tile2=(page<<8)+(tile&0xFF);
11387 redraw=true;
11388 }
11389 break;
11390
11391 case KEY_U:
11392 comeback_combos();
11393 redraw=true;
11394 break;
11395
11396 case KEY_E:
11397 go_combos();
11398 edit_combo(tile,false,cs);
11399 redraw=true;
11400 setup_combo_animations();
11401 setup_combo_animations2();
11402 break;
11403
11404 case KEY_C:
11405 go_combos();
11406 copy=zc_min(tile,tile2);
11407 copycnt=abs(tile-tile2)+1;
11408 redraw=true;
11409 break;
11410
11411 case KEY_H:
11412 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11413 {
11414 combobuf[i].flip^=1;
11415 byte w2=combobuf[i].walk;
11416 combobuf[i].walk=((w2& ~0x33)>>2 | (w2&0x33)<<2);
11417 w2=combobuf[i].csets;
11418 combobuf[i].csets= (((w2& ~0x50)>>1 | (w2&0x50)<<1) & ~0x0F) | (w2 & 0x0F);
11419 }
11420
11421 redraw=true;
11422 saved=false;
11423 break;
11424
11425 case KEY_M:
11426 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
11427 {
11428 move_combos(tile,tile2,copy,copycnt);
11429 saved=false;
11430 }
11431
11432 redraw=true;
11433 break;
11434
11435 case KEY_S:
11436 tile=tile2=zc_min(tile,tile2);
11437
11438 if(copy>=0 && tile!=copy)
11439 {
11440 go_combos();
11441
11442 for(int32_t i=0; i<copycnt; i++)
11443 {
11444 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11445 }
11446
11447 saved=false;
11448 setup_combo_animations();
11449 setup_combo_animations2();
11450 }
11451
11452 redraw=true;
11453 copy=-1;
11454 break;
11455
11456 case KEY_V:
11457 if((CHECK_CTRL_CMD) && copy != -1)
11458 {
11459 if(advpaste(tile, tile2, copy))
11460 {
11461 saved=false;
11462 redraw=true;
11463 copy=-1;
11464 }
11465
11466 break;
11467 }
11468
11469 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11470
11471 if(copy==-1)
11472 {
11473 go_combos();
11474
11475 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11476 {
11477 combobuf[i].flip^=2;
11478 byte w2=combobuf[i].walk;
11479 combobuf[i].walk=(w2&0x55)<<1 | (w2& ~0x55)>>1;
11480 w2=combobuf[i].csets;
11481 combobuf[i].csets= (((w2&0x30)<<2 | (w2& ~0x30)>>2) & ~0x0F) | (w2 & 0x0F);
11482 }
11483
11484 saved=false;
11485 }
11486 else
11487 {
11488 go_combos();
11489 copy_combos(tile,tile2,copy,copycnt,masscopy);
11490 setup_combo_animations();
11491 setup_combo_animations2();
11492 saved=false;
11493 }
11494
11495 redraw=true;
11496 break;
11497 case KEY_R:
11498 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11499 {
11500 combobuf[i].flip = rotate_value(combobuf[i].flip);
11501 combobuf[i].walk = rotate_walk(combobuf[i].walk);
11502 combobuf[i].csets = rotate_cset(combobuf[i].csets);
11503 }
11504
11505 redraw=true;
11506 saved=false;
11507 break;
11508
11509 case KEY_I:
11510 {
11511 // rev.1509; Can now insert/remove all selected combos
11512 int32_t z=tile;
11513 int32_t numSelected = abs(tile-tile2) + 1;
11514 tile=zc_min(tile,tile2);
11515 tile2=MAXCOMBOS;
11516 copy = tile + numSelected; // copy=tile+1;
11517 copycnt = MAXCOMBOS-tile-numSelected; // copycnt=MAXCOMBOS-tile;
11518
11519 if(key[KEY_LSHIFT]||key[KEY_RSHIFT])
11520 {
11521 char buf[64];
11522
11523 if(numSelected>1)
11524 sprintf(buf,"Remove combos %d - %d?",tile, copy-1);
11525 else
11526 sprintf(buf,"Remove combo %d?",tile);
11527
11528 if(jwin_alert("Confirm Remove",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11529 {
11530 move_combos(tile,tile2,copy, copycnt);
11531 //don't allow the user to undo; quest combo references are incorrect -DD
11532 go_combos();
11533 redraw=true;
11534 saved=false;
11535 }
11536 }
11537 else
11538 {
11539 char buf[64];
11540
11541 if(numSelected>1)
11542 sprintf(buf,"Insert %d blank combos?",numSelected);
11543 else
11544 sprintf(buf,"Insert a blank combo?");
11545
11546 if(jwin_alert("Confirm Insert",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11547 {
11548 move_combos(copy,tile2,tile, copycnt);
11549 go_combos();
11550 redraw=true;
11551 saved=false;
11552 }
11553 }
11554
11555 copy=-1;
11556 tile2=tile=z;
11557 }
11558 break;
11559
11560 case KEY_DEL:
11561 {
11562 char buf[40];
11563
11564 if(tile==tile2)
11565 {
11566 sprintf(buf,"Delete combo %d?",tile);
11567 }
11568 else
11569 {
11570 sprintf(buf,"Delete combos %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
11571 }
11572
11573 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11574 {
11575 go_combos();
11576
11577 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11578 {
11579 clear_combo(i);
11580 }
11581
11582 tile=tile2=zc_min(tile,tile2);
11583 redraw=true;
11584 saved=false;
11585 setup_combo_animations();
11586 setup_combo_animations2();
11587 }
11588 }
11589 break;
11590 }
11591
11592 clear_keybuf();
11593 }
11594
11595 if(gui_mouse_b()&1)
11596 {
11597 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
11598 {
11599 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
11600 {
11601 done=1;
11602 }
11603 }
11604
11605 int32_t x=gui_mouse_x()-screen_xofs;
11606 int32_t y=gui_mouse_y()-screen_yofs;
11607
11608 if(y>=0 && y<(208*mul))
11609 {
11610 x=zc_min(zc_max(x,0),(320*mul)-1);
11611 int32_t t;
11612
11613 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11614
11615 bound(t,0,255);
11616 t+=page<<8;
11617
11618 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
11619 {
11620 tile2=t;
11621 }
11622 else
11623 {
11624 tile=tile2=t;
11625 }
11626
11627 if(tile_clicked!=t)
11628 {
11629 dclick_status=DCLICK_NOT;
11630 }
11631 else if(dclick_status == DCLICK_AGAIN)
11632 {
11633 while(gui_mouse_b())
11634 {
11635 /* do nothing */
11636 rest(1);
11637 }
11638
11639 t2 = ((x>>6)*52) + ((x>>4)&3) + ((y>>4)<<2);
11640
11641 bound(t2,0,255);
11642 t2+=page<<8;
11643
11644 if(t2!=t)
11645 {
11646 dclick_status=DCLICK_NOT;
11647 }
11648 else
11649 {
11650 go_combos();
11651 edit_combo(tile,false,cs);
11652 redraw=true;
11653 setup_combo_animations();
11654 setup_combo_animations2();
11655 }
11656 }
11657
11658 tile_clicked=t;
11659 }
11660 else if(x>(300*mul) && !bdown)
11661 {
11662 if(y<(224*mul)+panel_yofs && page>0)
11663 {
11664 --page;
11665 redraw=true;
11666 }
11667
11668 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
11669 {
11670 ++page;
11671 redraw=true;
11672 }
11673
11674 bdown=true;
11675 }
11676
11677 if(!bdown && isinRect(x,y,(202*mul),(213*mul)+panel_yofs,(202+44)*mul,(213+21)*mul))
11678 {
11679 FONT *tf = font;
11680 font = tfont;
11681
11682 if(do_text_button((202*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Edit"))
11683 {
11684 font = tf;
11685 edit_combo(tile,false,cs);
11686 redraw=true;
11687 }
11688
11689 font = tf;
11690 }
11691 else if(!bdown && isinRect(x,y,(247*mul),(213*mul)+panel_yofs,(247+44)*mul,(213+21)*mul))
11692 {
11693 FONT *tf = font;
11694 font = tfont;
11695
11696 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11697 {
11698 done=1;
11699 }
11700
11701 font = tf;
11702 }
11703 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11704 {
11705 FONT *tf = font;
11706 font = tfont;
11707
11708 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11709 combopage_animate = combopage_animate ? 0 : 1;
11710 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11711 redraw = true;
11712
11713 font = tf;
11714 }
11715
11716 bdown=true;
11717 }
11718
11719 bool r_click = false;
11720
11721 if(gui_mouse_b()&2 && !bdown)
11722 {
11723 int32_t x=gui_mouse_x()-screen_xofs;
11724 int32_t y=gui_mouse_y()-screen_yofs;
11725
11726 if(y>=0 && y<(208*mul))
11727 {
11728 x=zc_min(zc_max(x,0),(320*mul)-1);
11729 int32_t t;
11730
11731 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11732
11733 bound(t,0,255);
11734 t+=page<<8;
11735
11736 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
11737 {
11738 tile=tile2=t;
11739 }
11740 }
11741
11742 bdown = r_click = true;
11743 f=8;
11744 }
11745
11746 REDRAW:
11747
11748 if(gui_mouse_b()==0)
11749 bdown=false;
11750
11751 if((f%8) || InvalidBG == 1)
11752 redraw = true;
11753 if(otl != tile || otl2 != tile2)
11754 {
11755 otl = tile;
11756 otl2 = tile2;
11757 redraw = true;
11758 }
11759
11760 if(redraw || combopage_animate)
11761 draw_combos(page,cs,true);
11762
11763 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11764
11765 if(f&8)
11766 {
11767 int32_t x,y;
11768
11769 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11770 {
11771 if((i>>8)==page)
11772 {
11773 int32_t t=i&255;
11774
11775 x=((t&3) + ((t/52)<<2)) << 5;
11776 y=((t%52)>>2) << 5;
11777
11778 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11779 }
11780 }
11781
11782 SCRFIX();
11783 }
11784
11785 ++f;
11786
11787 //Seriously? There is duplicate code for the r-click menu? -Gleeok
11788 if(r_click)
11789 {
11790 NewMenu rcmenu
11791 {
11792 { "Copy", [&]()
11793 {
11794 go_combos();
11795 copy=zc_min(tile,tile2);
11796 copycnt=abs(tile-tile2)+1;
11797 } },
11798 { "Paste", [&]()
11799 {
11800 if((CHECK_CTRL_CMD) && copy != -1)
11801 {
11802 if(advpaste(tile, tile2, copy))
11803 {
11804 saved=false;
11805 redraw=true;
11806 copy=-1;
11807 }
11808 return;
11809 }
11810
11811 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11812
11813 if(copy>-1)
11814 {
11815 go_combos();
11816 copy_combos(tile,tile2,copy,copycnt,masscopy);
11817 setup_combo_animations();
11818 setup_combo_animations2();
11819 saved=false;
11820 }
11821 } },
11822 { "Adv. Paste", [&]()
11823 {
11824 if(copy > -1)
11825 {
11826 if(advpaste(tile, tile2, copy))
11827 {
11828 saved=false;
11829 redraw=true;
11830 copy=-1;
11831 }
11832 }
11833 } },
11834 { "Swap", [&]()
11835 {
11836 tile=tile2=zc_min(tile,tile2);
11837
11838 if(copy>=0 && tile!=copy)
11839 {
11840 go_combos();
11841
11842 for(int32_t i=0; i<copycnt; i++)
11843 {
11844 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11845 }
11846
11847 saved=false;
11848 setup_combo_animations();
11849 setup_combo_animations2();
11850 }
11851 copy=-1;
11852 } },
11853 { "Delete", [&]()
11854 {
11855 string msg;
11856
11857 if(tile==tile2)
11858 msg = fmt::format("Delete combo {}?",tile);
11859 else
11860 msg = fmt::format("Delete combos {}-{}?",zc_min(tile,tile2),zc_max(tile,tile2));
11861 bool didconfirm = false;
11862 AlertDialog("Confirm Delete",msg,
11863 [&](bool ret,bool)
11864 {
11865 if(ret)
11866 didconfirm = true;
11867 }).show();
11868 if(didconfirm)
11869 {
11870 go_combos();
11871
11872 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11873 clear_combo(i);
11874
11875 tile=tile2=zc_min(tile,tile2);
11876 saved=false;
11877 }
11878 } },
11879 {},
11880 { "Edit", [&]()
11881 {
11882 go_combos();
11883 edit_combo(tile,false,cs);
11884 } },
11885 { "Insert", [&]()
11886 {
11887 int z = tile;
11888 int count = abs(tile-tile2)+1;
11889 tile = zc_min(tile,tile2);
11890 tile2 = MAXCOMBOS;
11891 copy = tile+count;
11892 copycnt = MAXCOMBOS-tile-count;
11893
11894 string msg;
11895
11896 if(count>1)
11897 msg = fmt::format("Insert combos {} - {}?"
11898 " This will offset all of the combos that follow!",tile, copy-1);
11899 else
11900 msg = fmt::format("Insert combo {}?"
11901 " This will offset all of the combos that follow!",tile);
11902
11903 bool didconfirm = false;
11904 AlertDialog("Confirm Insert",msg,
11905 [&](bool ret,bool)
11906 {
11907 if(ret)
11908 didconfirm = true;
11909 }).show();
11910 if(didconfirm)
11911 move_combos(copy, tile2, tile, copycnt);
11912 else return;
11913
11914 copy = -1;
11915 tile2 = tile = z;
11916
11917 //don't allow the user to undo; quest combo references are incorrect -DD
11918 go_combos();
11919 saved = false;
11920 } },
11921 { "Remove", [&]()
11922 {
11923 int z = tile;
11924 int count = abs(tile-tile2)+1;
11925 tile = zc_min(tile,tile2);
11926 tile2 = MAXCOMBOS;
11927 copy = tile+count;
11928 copycnt = MAXCOMBOS-tile-count;
11929
11930 string msg;
11931
11932 if(count>1)
11933 msg = fmt::format("Remove combos {} - {}?"
11934 " This will offset all of the combos that follow!",tile, copy-1);
11935 else
11936 msg = fmt::format("Remove combo {}?"
11937 " This will offset all of the combos that follow!",tile);
11938
11939 bool didconfirm = false;
11940 AlertDialog("Confirm Remove",msg,
11941 [&](bool ret,bool)
11942 {
11943 if(ret)
11944 didconfirm = true;
11945 }).show();
11946 if(didconfirm)
11947 move_combos(tile, tile2, copy, copycnt);
11948 else return;
11949
11950 copy = -1;
11951 tile2 = tile = z;
11952
11953 //don't allow the user to undo; quest combo references are incorrect -DD
11954 go_combos();
11955 saved = false;
11956 } },
11957 {},
11958 { "Locations", [&]()
11959 {
11960 int32_t z = Combo;
11961 Combo = tile;
11962 onComboLocationReport();
11963 Combo = z;
11964 } },
11965 };
11966 rcmenu.pop(window_mouse_x(),window_mouse_y());
11967 redraw = true;
11968 r_click = false;
11969 goto REDRAW;
11970 }
11971
11972 }
11973 while(!done);
11974
11975 while(gui_mouse_b())
11976 rest(1);
11977 comeback();
11978 setup_combo_animations();
11979 setup_combo_animations2();
11980 _selected_combo = tile;
11981 _selected_cset = cs;
11982 popup_zqdialog_end();
11983 return done-1;
11984 }
11985
11986 int32_t onCombos()
11987 {
11988 combo_screen(-1,-1);
11989 refresh(rALL);
11990 return D_O_K;
11991 }
11992
11993 int32_t d_ctile_proc(int32_t msg,DIALOG *d,int32_t c)
11994 {
11995 //these are here to bypass compiler warnings about unused arguments
11996 d=d;
11997 c=c;
11998
11999 if(msg==MSG_CLICK)
12000 {
12001 int32_t t=curr_combo.o_tile;
12002 int32_t f=curr_combo.flip;
12003
12004 if(select_tile(t,f,1,CSet,true,0,true))
12005 {
12006 curr_combo.tile=t;
12007 curr_combo.o_tile=t;
12008 curr_combo.flip=f;
12009 return D_REDRAW;
12010 }
12011 }
12012
12013 return D_O_K;
12014 }
12015
12016 int32_t d_combo_loader(int32_t msg,DIALOG *d,int32_t c)
12017 {
12018 //these are here to bypass compiler warnings about unused arguments
12019 c=c;
12020
12021 if(msg==MSG_DRAW)
12022 {
12023 FONT *f = get_zc_font(font_lfont_l);
12024 textprintf_ex(screen,f,d->x,d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Tile:");
12025 textprintf_ex(screen,f,d->x+((1.5)*36),d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.o_tile);
12026 textprintf_ex(screen,f,d->x,d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
12027 textprintf_ex(screen,f,d->x+((1.5)*36),d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.flip);
12028 textprintf_ex(screen,f,d->x,d->y+(36),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet2:");
12029 }
12030
12031 return D_O_K;
12032 }
12033
12034 int32_t click_d_ctile_proc()
12035 {
12036 d_ctile_proc(MSG_CLICK,NULL,0);
12037 return D_REDRAW;
12038 }
12039
12040 int32_t click_d_combo_proc();
12041
12042 const char *comboscriptdroplist(int32_t index, int32_t *list_size)
12043 {
12044 if(index<0)
12045 {
12046 *list_size = bidcomboscripts_cnt;
12047 return NULL;
12048 }
12049
12050 return bidcomboscripts[index].first.c_str();
12051 }
12052 12 ListData comboscript_list(comboscriptdroplist, &font);
12053
12054 bool call_combo_editor(int32_t);
12055 bool edit_combo(int32_t c,bool freshen,int32_t cs)
12056 {
12057 FONT* ofont = font;
12058 //CSet = cs;
12059 reset_combo_animations();
12060 reset_combo_animations2();
12061 bool edited = call_combo_editor(c);
12062 font = ofont;
12063
12064 if(freshen)
12065 {
12066 refresh(rALL);
12067 }
12068
12069 setup_combo_animations();
12070 setup_combo_animations2();
12071
12072 return edited;
12073 }
12074
12075 int32_t d_itile_proc(int32_t msg,DIALOG *d,int32_t)
12076 {
12077 switch(msg)
12078 {
12079 case MSG_CLICK:
12080 {
12081 int32_t cs = d->d2;
12082 int32_t f = 0;
12083
12084 if(select_tile(d->d1,f,1,cs,true))
12085 {
12086 int32_t ok=1;
12087
12088 if(newtilebuf[d->d1].format==tf8Bit)
12089 jwin_alert("Warning",
12090 "You have selected an 8-bit tile.",
12091 "It will not be drawn correctly",
12092 "on the file select screen.",
12093 "&OK",NULL,'o',0,get_zc_font(font_lfont));
12094
12095 return D_REDRAW;
12096 }
12097 }
12098 break;
12099
12100 case MSG_DRAW:
12101 d->w = 32+4;
12102 d->h = 32+4;
12103
12104 BITMAP *buf = create_bitmap_ex(8,16,16);
12105 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12106
12107 if(buf && bigbmp)
12108 {
12109 clear_bitmap(buf);
12110 overtile16(buf,d->d1,0,0,d->fg,0);
12111 stretch_blit(buf, bigbmp, 0,0, 16, 16, 2, 2, d->w-4, d->h-4);
12112 destroy_bitmap(buf);
12113 jwin_draw_frame(bigbmp,0, 0, d->w,d->h, FR_DEEP);
12114 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12115 destroy_bitmap(bigbmp);
12116 }
12117
12118 break;
12119 }
12120
12121 return D_O_K;
12122 }
12123
12124 static DIALOG icon_dlg[] =
12125 {
12126 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
12127 { jwin_win_proc, 70, 70, 170, 104, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Game Icons", NULL, NULL },
12128 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
12129 { d_itile_proc, 108+3, 112, 20, 20, 0, 0, 0, 0, 0, 6, NULL, NULL, NULL },
12130 { d_itile_proc, 138+3, 112, 20, 20, 0, 0, 0, 0, 0, 7, NULL, NULL, NULL },
12131 { d_itile_proc, 168+3, 112, 20, 20, 0, 0, 0, 0, 0, 8, NULL, NULL, NULL },
12132 { d_itile_proc, 198+3, 112, 20, 20, 0, 0, 0, 0, 0, 9, NULL, NULL, NULL },
12133 { jwin_button_proc, 90, 145, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12134 { jwin_button_proc, 170, 145, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12135 { jwin_text_proc, 108+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "0", NULL, NULL },
12136 { jwin_text_proc, 138+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "1", NULL, NULL },
12137 { jwin_text_proc, 168+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "2", NULL, NULL },
12138 { jwin_text_proc, 198+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "3+", NULL, NULL },
12139 { jwin_text_proc, 88, 98, 12, 9, 0, 0, 0, 0, 0, 0, (void *) "Ring:", NULL, NULL },
12140 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12141 };
12142
12143 int32_t onIcons()
12144 {
12145 PALETTE pal;
12146 // pal = RAMpal;
12147 memcpy(pal,RAMpal,sizeof(RAMpal));
12148 icon_dlg[0].dp2=get_zc_font(font_lfont);
12149
12150 for(int32_t i=0; i<4; i++)
12151 {
12152 icon_dlg[i+2].d1 = QMisc.icons[i];
12153 icon_dlg[i+2].fg = i+6;
12154 load_cset(pal, i+6, pSprite(i+spICON1));
12155 }
12156
12157 zc_set_palette(pal);
12158
12159 large_dialog(icon_dlg);
12160
12161 int32_t ret = do_zqdialog(icon_dlg,7);
12162
12163 if(ret==6)
12164 {
12165 for(int32_t i=0; i<4; i++)
12166 {
12167 if(QMisc.icons[i] != icon_dlg[i+2].d1)
12168 {
12169 QMisc.icons[i] = icon_dlg[i+2].d1;
12170 saved=false;
12171 }
12172 }
12173 }
12174
12175 zc_set_palette(RAMpal);
12176 return D_O_K;
12177 }
12178
12179 // Identical to jwin_frame_proc, but is treated differently by large_dialog()
12180 int32_t d_comboframe_proc(int32_t msg, DIALOG *d, int32_t)
12181 {
12182 if(msg == MSG_DRAW)
12183 {
12184 jwin_draw_frame(screen, d->x, d->y, d->w, d->h, d->d1);
12185 }
12186
12187 return D_O_K;
12188 }
12189
12190 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t)
12191 {
12192 switch(msg)
12193 {
12194 case MSG_CLICK:
12195 {
12196 if((d->flags&D_NOCLICK))
12197 break;
12198
12199 int32_t ret = (d->flags & D_EXIT) ? D_CLOSE : D_O_K;
12200 int32_t combo2;
12201 int32_t cs;
12202
12203 if(CHECK_ALT) //place selected cmb/cs
12204 {
12205 if(gui_mouse_b()&1)
12206 {
12207 if(!CHECK_SHIFT)
12208 d->d1 = Combo;
12209 d->fg = CSet;
12210 }
12211
12212 return ret|D_REDRAW;
12213 }
12214 else if(gui_mouse_b()&2||nextcombo_fake_click==2) //clear to 0/0
12215 {
12216 d->d1=0;
12217 d->fg=0;
12218 return ret|D_REDRAW;
12219 }
12220 else if(gui_mouse_b()&1||nextcombo_fake_click==1) //popup combo picker
12221 {
12222 combo2=d->d1;
12223 cs=d->fg;
12224
12225 if((CHECK_CTRL_CMD ? select_combo_3 : select_combo_2)(combo2, cs))
12226 {
12227 d->d1=combo2;
12228 d->fg=cs;
12229 }
12230
12231 return ret|D_REDRAW;
12232 }
12233 else return ret|D_REDRAWME;
12234 }
12235 break;
12236
12237 case MSG_DRAW:
12238 {
12239 d->w = 32;
12240 d->h = 32;
12241
12242 BITMAP *buf = create_bitmap_ex(8,16,16);
12243 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12244
12245 if(buf && bigbmp)
12246 {
12247 clear_bitmap(buf);
12248
12249 if(d->d1==-1) // Display curr_combo instead of combobuf
12250 {
12251 newcombo hold = combobuf[0];
12252 combobuf[0] = curr_combo;
12253 putcombo(buf,0,0,0,d->fg);
12254 combobuf[0] = hold;
12255 }
12256 else if(d->d1)
12257 {
12258 putcombo(buf,0,0,d->d1,d->fg);
12259 }
12260
12261 stretch_blit(buf, bigbmp, 0,0, 16, 16, 0, 0, d->w, d->h);
12262 destroy_bitmap(buf);
12263 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12264 destroy_bitmap(bigbmp);
12265 }
12266 }
12267 break;
12268 }
12269 return D_O_K;
12270 }
12271
12272 // Hey, let's have a few hundred more lines of code, why not.
12273
12274 #define MR_4BIT 0
12275 #define MR_8BIT 1
12276
12277 static byte massRecolorSrc4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12278 static byte massRecolorDest4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12279 static word massRecolor8BitCSets=0; // Which CSets are affected? One bit each.
12280
12281 static byte massRecolorSrc8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12282 static byte massRecolorDest8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12283
12284 static int32_t massRecolorDraggedColor=-1;
12285 static int32_t massRecolorCSet;
12286 static bool massRecolorIgnoreBlank=true;
12287 static byte massRecolorType=MR_4BIT;
12288
12289 // Shows the sets of colors to replace from/to.
12290 // D_CSET: Colors are 0-15 within the current CSet rather than absolute.
12291 // D_SETTABLE: Colors can be dragged and dropped onto this one.
12292 #define D_CSET D_USER
12293 #define D_SETTABLE (D_USER<<1)
12294 int32_t d_mr_cset_proc(int32_t msg, DIALOG* d, int32_t)
12295 {
12296 BITMAP* bmp=screen;
12297 int32_t colorWidth=(d->w-4)/16;
12298 byte* colors=static_cast<byte*>(d->dp);
12299
12300 switch(msg)
12301 {
12302 case MSG_DRAW:
12303 {
12304 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12305
12306 int32_t baseColor=((d->flags&D_CSET)!=0) ? massRecolorCSet*16 : 0;
12307 for(int32_t c=0; c<16; c++)
12308 {
12309 rectfill(bmp,
12310 d->x+2+c*colorWidth, d->y+2,
12311 d->x+2+((c+1)*colorWidth)-1, d->y+2+d->h-5,
12312 baseColor+colors[c]);
12313 }
12314 }
12315 break;
12316
12317 case MSG_LPRESS:
12318 {
12319 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12320
12321 if(x >= 0 && x < 16) //sanity check!
12322 {
12323 massRecolorDraggedColor=colors[x];
12324 }
12325 }
12326 break;
12327
12328 case MSG_LRELEASE: // This isn't exactly right, but it'll do...
12329 if((d->flags&D_SETTABLE)!=0 && massRecolorDraggedColor>=0)
12330 {
12331 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12332 if(x >= 0 && x < 16) //sanity check!
12333 {
12334 colors[x]=massRecolorDraggedColor;
12335 d->flags|=D_DIRTY;
12336 }
12337 }
12338 massRecolorDraggedColor=-1;
12339 break;
12340 }
12341
12342 return D_O_K;
12343 }
12344
12345 // Used for the full palette in 8-bit mode.
12346 static int32_t d_mr_palette_proc(int32_t msg, DIALOG* d, int32_t)
12347 {
12348 BITMAP* bmp=screen;
12349 int colorWidth=(d->w-4)/16;
12350 d->h = 4+(colorWidth*14);
12351 int colorHeight=colorWidth;
12352
12353 switch(msg)
12354 {
12355 case MSG_DRAW:
12356 {
12357 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12358 for(int cset=0; cset<=13; cset++)
12359 {
12360 for(int color=0; color<16; color++)
12361 {
12362 rectfill(bmp,
12363 d->x+2+color*colorWidth,
12364 d->y+2+cset*colorHeight,
12365 d->x+2+((color+1)*colorWidth)-1,
12366 d->y+2+((cset+1)*colorHeight)-1,
12367 cset*16+color);
12368 }
12369 }
12370 }
12371 break;
12372
12373 case MSG_LPRESS:
12374 {
12375 int cset=(gui_mouse_y()-(d->y+2))/colorHeight;
12376 int color=(gui_mouse_x()-(d->x+2))/colorWidth;
12377 massRecolorDraggedColor=cset*16+color;
12378 }
12379 break;
12380 }
12381
12382 return D_O_K;
12383 }
12384
12385 static DIALOG recolor_4bit_dlg[] =
12386 {
12387 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12388 { jwin_win_proc, 0, 0, 216, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12389
12390 // 1
12391 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12392 { d_mr_cset_proc, 10, 42, 196, 16, 0, 0, 0, D_CSET, 0, 0, (void *)massRecolorSrc4Bit, NULL, NULL },
12393 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12394 { d_mr_cset_proc, 10, 70, 196, 16, 0, 0, 0, D_CSET|D_SETTABLE, 0, 0, (void *)massRecolorDest4Bit, NULL, NULL },
12395
12396 // 5
12397 { jwin_text_proc, 12, 96, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Apply to which CSets in 8-bit tiles?", NULL, NULL },
12398 { jwin_check_proc, 12, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "0", NULL, NULL },
12399 { jwin_check_proc, 36, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "1", NULL, NULL },
12400 { jwin_check_proc, 60, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "2", NULL, NULL },
12401 { jwin_check_proc, 84, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "3", NULL, NULL },
12402 { jwin_check_proc, 108, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "4", NULL, NULL },
12403 { jwin_check_proc, 132, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "5", NULL, NULL },
12404 { jwin_check_proc, 156, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "6", NULL, NULL },
12405 { jwin_check_proc, 12, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "7", NULL, NULL },
12406 { jwin_check_proc, 36, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "8", NULL, NULL },
12407 { jwin_check_proc, 60, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "9", NULL, NULL },
12408 { jwin_check_proc, 84, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "10", NULL, NULL },
12409 { jwin_check_proc, 108, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "11", NULL, NULL },
12410 { jwin_check_proc, 132, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "12", NULL, NULL },
12411 { jwin_check_proc, 156, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "13", NULL, NULL },
12412
12413 // 20
12414 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12415 { jwin_func_button_proc, 14, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset4Bit },
12416 { jwin_button_proc, 82, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 8-bit mode", NULL, NULL },
12417 { jwin_button_proc, 44, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12418 { jwin_button_proc, 112, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12419
12420 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12421 };
12422
12423 #define MR4_SRC_COLORS 2
12424 #define MR4_DEST_COLORS 4
12425 #define MR4_8BIT_EFFECT_START 6
12426 #define MR4_IGNORE_BLANK 20
12427 #define MR4_RESET 21
12428 #define MR4_SWITCH 22
12429 #define MR4_OK 23
12430 #define MR4_CANCEL 24
12431
12432 static DIALOG recolor_8bit_dlg[] =
12433 {
12434 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12435 { jwin_win_proc, 0, 0, 288, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12436
12437 // 1
12438 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12439 { d_mr_cset_proc, 10, 42, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorSrc8Bit, NULL, NULL },
12440 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12441 { d_mr_cset_proc, 10, 70, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorDest8Bit, NULL, NULL },
12442 { d_mr_palette_proc, 144, 32, 132, 150, vc(15), vc(1), 0, 0, 0, 0, (void *) NULL, NULL, NULL },
12443
12444 // 6
12445 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12446 { jwin_func_button_proc, 50, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset8Bit },
12447 { jwin_button_proc, 118, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 4-bit mode", NULL, NULL },
12448 { jwin_button_proc, 80, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12449 { jwin_button_proc, 148, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12450
12451 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12452 };
12453
12454 #define MR8_SRC_COLORS 2
12455 #define MR8_DEST_COLORS 4
12456 #define MR8_PALETTE 5
12457 #define MR8_IGNORE_BLANK 6
12458 #define MR8_RESET 7
12459 #define MR8_SWITCH 8
12460 #define MR8_OK 9
12461 #define MR8_CANCEL 10
12462
12463 static void massRecolorInit(int32_t cset)
12464 {
12465 massRecolorDraggedColor=-1;
12466 massRecolorCSet=cset;
12467
12468 recolor_4bit_dlg[0].dp2=get_zc_font(font_lfont);
12469 recolor_8bit_dlg[0].dp2=get_zc_font(font_lfont);
12470
12471 for(int32_t i=0; i<=13; i++)
12472 {
12473 if((massRecolor8BitCSets&(1<<i))!=0)
12474 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags|=D_SELECTED;
12475 else
12476 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&=~D_SELECTED;
12477 }
12478
12479 if(massRecolorIgnoreBlank)
12480 {
12481 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags|=D_SELECTED;
12482 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags|=D_SELECTED;
12483 }
12484 else
12485 {
12486 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&=~D_SELECTED;
12487 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&=~D_SELECTED;
12488 }
12489
12490 large_dialog(recolor_4bit_dlg);
12491 large_dialog(recolor_8bit_dlg);
12492
12493 // Quick fix for large_dialog() screwing these up. It's ugly. Whatever.
12494 if((recolor_4bit_dlg[MR4_DEST_COLORS].w-4)%4!=0)
12495 {
12496 recolor_4bit_dlg[MR4_SRC_COLORS].x++;
12497 recolor_4bit_dlg[MR4_SRC_COLORS].w-=2;
12498 recolor_4bit_dlg[MR4_DEST_COLORS].x++;
12499 recolor_4bit_dlg[MR4_DEST_COLORS].w-=2;
12500
12501 recolor_8bit_dlg[MR8_SRC_COLORS].x++;
12502 recolor_8bit_dlg[MR8_SRC_COLORS].w-=2;
12503 recolor_8bit_dlg[MR8_DEST_COLORS].x++;
12504 recolor_8bit_dlg[MR8_DEST_COLORS].w-=2;
12505 recolor_8bit_dlg[MR8_PALETTE].x++;
12506 recolor_8bit_dlg[MR8_PALETTE].w-=2;
12507 recolor_8bit_dlg[MR8_PALETTE].y++;
12508 recolor_8bit_dlg[MR8_PALETTE].h-=2;
12509 }
12510 }
12511
12512 static void massRecolorApplyChanges()
12513 {
12514 massRecolor8BitCSets=0;
12515 for(int32_t i=0; i<=13; i++)
12516 {
12517 if((recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&D_SELECTED)!=0)
12518 massRecolor8BitCSets|=1<<i;
12519 }
12520
12521 if(massRecolorType==MR_4BIT)
12522 massRecolorIgnoreBlank=(recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&D_SELECTED)!=0;
12523 else
12524 massRecolorIgnoreBlank=(recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&D_SELECTED)!=0;
12525 }
12526
12527 static bool massRecolorSetup(int32_t cset)
12528 {
12529 massRecolorInit(cset);
12530
12531 // Remember the current colors in case the user cancels.
12532 int32_t oldDest4Bit[16], oldSrc8Bit[16], oldDest8Bit[16];
12533 for(int32_t i=0; i<16; i++)
12534 {
12535 oldDest4Bit[i]=massRecolorDest4Bit[i];
12536 oldSrc8Bit[i]=massRecolorSrc8Bit[i];
12537 oldDest8Bit[i]=massRecolorDest8Bit[i];
12538 }
12539
12540 byte type=massRecolorType;
12541 int32_t ret;
12542 do
12543 {
12544 HANDLE_CLOSE_ZQDLG();
12545 if(exiting_program) break;
12546 if(type==MR_4BIT)
12547 {
12548 ret=do_zqdialog(recolor_4bit_dlg, MR4_OK);
12549 if(ret==MR4_SWITCH)
12550 type=MR_8BIT;
12551 }
12552 else
12553 {
12554 ret=do_zqdialog(recolor_8bit_dlg, MR8_OK);
12555 if(ret==MR8_SWITCH)
12556 type=MR_4BIT;
12557 }
12558 } while(ret==MR4_SWITCH || ret==MR8_SWITCH);
12559
12560 if(ret!=MR4_OK && ret!=MR8_OK) // Canceled
12561 {
12562 for(int32_t i=0; i<16; i++)
12563 {
12564 massRecolorDest4Bit[i]=oldDest4Bit[i];
12565 massRecolorSrc8Bit[i]=oldSrc8Bit[i];
12566 massRecolorDest8Bit[i]=oldDest8Bit[i];
12567 }
12568 return false;
12569 }
12570
12571 // OK
12572 massRecolorType=type;
12573 massRecolorApplyChanges();
12574 return true;
12575 }
12576
12577 static void massRecolorApply4Bit(int32_t tile)
12578 {
12579 byte buf[256];
12580 unpack_tile(newtilebuf, tile, 0, true);
12581
12582 if(newtilebuf[tile].format==tf4Bit)
12583 {
12584 for(int32_t i=0; i<256; i++)
12585 buf[i]=massRecolorDest4Bit[unpackbuf[i]];
12586 }
12587 else // 8-bit
12588 {
12589 for(int32_t i=0; i<256; i++)
12590 {
12591 word cset=unpackbuf[i]>>4;
12592 if((massRecolor8BitCSets&(1<<cset))!=0) // Recolor this CSet?
12593 {
12594 word color=unpackbuf[i]&15;
12595 buf[i]=(cset<<4)|massRecolorDest4Bit[color];
12596 }
12597 else
12598 buf[i]=unpackbuf[i];
12599 }
12600 }
12601
12602 pack_tile(newtilebuf, buf, tile);
12603 }
12604
12605 static void massRecolorApply8Bit(int32_t tile)
12606 {
12607 byte buf[256];
12608 unpack_tile(newtilebuf, tile, 0, true);
12609
12610 for(int32_t i=0; i<256; i++)
12611 {
12612 byte color=unpackbuf[i];
12613 for(int32_t j=0; j<16; j++)
12614 {
12615 if(massRecolorSrc8Bit[j]==color)
12616 {
12617 color=massRecolorDest8Bit[j];
12618 break;
12619 }
12620 }
12621 buf[i]=color;
12622 }
12623
12624 pack_tile(newtilebuf, buf, tile);
12625 }
12626
12627 static void massRecolorApply(int32_t tile)
12628 {
12629 if(massRecolorIgnoreBlank && blank_tile_table[tile])
12630 return;
12631
12632 if(massRecolorType==MR_4BIT)
12633 massRecolorApply4Bit(tile);
12634 else // 8-bit
12635 {
12636 if(newtilebuf[tile].format==tf4Bit)
12637 return;
12638 massRecolorApply8Bit(tile);
12639 }
12640 }
12641
12642 static void massRecolorReset4Bit()
12643 {
12644 for(int32_t i=0; i<16; i++)
12645 massRecolorDest4Bit[i]=i;
12646 recolor_4bit_dlg[MR4_DEST_COLORS].flags|=D_DIRTY;
12647 }
12648
12649 static void massRecolorReset8Bit()
12650 {
12651 for(int32_t i=0; i<16; i++)
12652 {
12653 massRecolorSrc8Bit[i]=0;
12654 massRecolorDest8Bit[i]=0;
12655 }
12656
12657 recolor_8bit_dlg[MR8_SRC_COLORS].flags|=D_DIRTY;
12658 recolor_8bit_dlg[MR8_DEST_COLORS].flags|=D_DIRTY;
12659 }
12660
12661 8 void center_zq_tiles_dialogs()
12662 {
12663 8 jwin_center_dialog(create_relational_tiles_dlg);
12664 8 jwin_center_dialog(icon_dlg);
12665 8 jwin_center_dialog(leech_dlg);
12666 8 jwin_center_dialog(move_textbox_list_dlg);
12667 8 jwin_center_dialog(recolor_4bit_dlg);
12668 8 jwin_center_dialog(recolor_8bit_dlg);
12669 8 }
12670
12671 //.ZCOMBO
12672
12673 int32_t readcombo_loop(PACKFILE* f, word section_version, newcombo& temp_combo);
12674 int32_t writecombo_loop(PACKFILE *f, word section_version, newcombo const& tmp_cmb);
12675
12676 int32_t readcombofile_old(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t zversion,
12677 dword section_version, int32_t index, int32_t count)
12678 {
12679 newcombo temp_combo;
12680 for ( int32_t tilect = 0; tilect < count; tilect++ )
12681 {
12682 temp_combo.clear();
12683 if(!p_igetw(&temp_combo.tile,f))
12684 {
12685 return 0;
12686 }
12687 temp_combo.o_tile = temp_combo.tile;
12688
12689 if(!p_getc(&temp_combo.flip,f))
12690 {
12691 return 0;
12692 }
12693
12694 if(!p_getc(&temp_combo.walk,f))
12695 {
12696 return 0;
12697 }
12698
12699 if(!p_getc(&temp_combo.type,f))
12700 {
12701 return 0;
12702 }
12703
12704 if(!p_getc(&temp_combo.csets,f))
12705 {
12706 return 0;
12707 }
12708
12709 if(!p_getc(&temp_combo.frames,f))
12710 {
12711 return 0;
12712 }
12713
12714 if(!p_getc(&temp_combo.speed,f))
12715 {
12716 return 0;
12717 }
12718
12719 if(!p_igetw(&temp_combo.nextcombo,f))
12720 {
12721 return 0;
12722 }
12723
12724 if(!p_getc(&temp_combo.nextcset,f))
12725 {
12726 return 0;
12727 }
12728
12729 if(!p_getc(&temp_combo.flag,f))
12730 {
12731 return 0;
12732 }
12733
12734 if(!p_getc(&temp_combo.skipanim,f))
12735 {
12736 return 0;
12737 }
12738
12739 if(!p_igetw(&temp_combo.nexttimer,f))
12740 {
12741 return 0;
12742 }
12743
12744 if(!p_getc(&temp_combo.skipanimy,f))
12745 {
12746 return 0;
12747 }
12748
12749 if(!p_getc(&temp_combo.animflags,f))
12750 {
12751 return 0;
12752 }
12753
12754 //2.55 starts here
12755 if ( zversion >= 0x255 )
12756 {
12757 if ( section_version >= 12 )
12758 {
12759 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12760 {
12761 if(!p_igetl(&temp_combo.attributes[q],f))
12762 {
12763 return 0;
12764 }
12765 }
12766 if(!p_igetl(&temp_combo.usrflags,f))
12767 {
12768 return 0;
12769 }
12770 for ( int32_t q = 0; q < 3; q++ )
12771 {
12772 if(!p_igetl(&temp_combo.triggerflags[q],f))
12773 {
12774 return 0;
12775 }
12776 }
12777
12778 if(!p_igetl(&temp_combo.triggerlevel,f))
12779 {
12780 return 0;
12781 }
12782 if(section_version >= 22)
12783 {
12784 if(!p_getc(&temp_combo.triggerbtn,f))
12785 {
12786 return 0;
12787 }
12788 }
12789 if(section_version < 23)
12790 {
12791 switch(temp_combo.type) //combotriggerCMBTYPEFX now required for combotype-specific effects
12792 {
12793 case cSCRIPT1: case cSCRIPT2: case cSCRIPT3: case cSCRIPT4: case cSCRIPT5:
12794 case cSCRIPT6: case cSCRIPT7: case cSCRIPT8: case cSCRIPT9: case cSCRIPT10:
12795 case cTRIGGERGENERIC: case cCSWITCH:
12796 temp_combo.triggerflags[0] |= combotriggerCMBTYPEFX;
12797 }
12798 }
12799 if(section_version >= 24)
12800 {
12801 if(!p_getc(&temp_combo.triggeritem,f))
12802 {
12803 return 0;
12804 }
12805 if(!p_getc(&temp_combo.trigtimer,f))
12806 {
12807 return 0;
12808 }
12809 }
12810 if(section_version >= 25)
12811 {
12812 if(!p_getc(&temp_combo.trigsfx,f))
12813 {
12814 return 0;
12815 }
12816 }
12817 else
12818 {
12819 switch(temp_combo.type)
12820 {
12821 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
12822 if(!(temp_combo.usrflags & cflag3))
12823 temp_combo.attribytes[3] = WAV_DOOR;
12824 temp_combo.usrflags &= ~cflag3;
12825 break;
12826 }
12827 }
12828 if(section_version < 26)
12829 {
12830 if(temp_combo.type == cARMOS)
12831 {
12832 if(temp_combo.usrflags & cflag1)
12833 temp_combo.usrflags |= cflag3;
12834 }
12835 }
12836 if(section_version >= 27)
12837 {
12838 if(!p_igetl(&temp_combo.trigchange,f))
12839 {
12840 return qe_invalid;
12841 }
12842 }
12843 else
12844 {
12845 if(temp_combo.triggerflags[0] & 0x00040000) //'next'
12846 temp_combo.trigchange = 1;
12847 else if(temp_combo.triggerflags[0] & 0x00080000) //'prev'
12848 temp_combo.trigchange = -1;
12849 else temp_combo.trigchange = 0;
12850 temp_combo.triggerflags[0] &= ~(0x00040000|0x00080000);
12851 }
12852 if(section_version >= 29)
12853 {
12854 if(!p_igetw(&temp_combo.trigprox,f))
12855 {
12856 return qe_invalid;
12857 }
12858 if(!p_getc(&temp_combo.trigctr,f))
12859 {
12860 return qe_invalid;
12861 }
12862 if(!p_igetl(&temp_combo.trigctramnt,f))
12863 {
12864 return qe_invalid;
12865 }
12866 }
12867 else
12868 {
12869 temp_combo.trigprox = 0;
12870 temp_combo.trigctr = 0;
12871 temp_combo.trigctramnt = 0;
12872 }
12873 if(section_version >= 30)
12874 {
12875 if(!p_getc(&temp_combo.triglbeam,f))
12876 {
12877 return qe_invalid;
12878 }
12879 }
12880 else temp_combo.triglbeam = 0;
12881 if(section_version >= 31)
12882 {
12883 if(!p_getc(&temp_combo.trigcschange,f))
12884 {
12885 return qe_invalid;
12886 }
12887 if(!p_igetw(&temp_combo.spawnitem,f))
12888 {
12889 return qe_invalid;
12890 }
12891 if(!p_igetw(&temp_combo.spawnenemy,f))
12892 {
12893 return qe_invalid;
12894 }
12895 if(!p_getc(&temp_combo.exstate,f))
12896 {
12897 return qe_invalid;
12898 }
12899 if(!p_igetl(&temp_combo.spawnip,f))
12900 {
12901 return qe_invalid;
12902 }
12903 if(!p_getc(&temp_combo.trigcopycat,f))
12904 {
12905 return qe_invalid;
12906 }
12907 }
12908 else
12909 {
12910 temp_combo.trigcschange = 0;
12911 temp_combo.spawnitem = 0;
12912 temp_combo.spawnenemy = 0;
12913 temp_combo.exstate = -1;
12914 temp_combo.spawnip = 0;
12915 temp_combo.trigcopycat = 0;
12916 }
12917 if(section_version >= 32)
12918 {
12919 if(!p_getc(&temp_combo.trigcooldown,f))
12920 {
12921 return qe_invalid;
12922 }
12923 }
12924 else
12925 {
12926 temp_combo.trigcooldown = 0;
12927 }
12928 char label[12];
12929 label[11] = '\0';
12930 for ( int32_t q = 0; q < 11; q++ )
12931 {
12932 if(!p_getc(&label[q],f))
12933 {
12934 return 0;
12935 }
12936 }
12937 temp_combo.label = label;
12938 }
12939 if ( section_version >= 13 )
12940 {
12941 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12942 {
12943 if(!p_getc(&temp_combo.attribytes[q],f))
12944 {
12945 return 0;
12946 }
12947 }
12948
12949 }
12950 }
12951
12952 if ( !(skip && (index+(tilect-1)) < skip) ) //is -1 still needed here?
12953 {
12954 if ( !nooverwrite || combobuf[index+tilect].is_blank() )
12955 {
12956 combobuf[index+(tilect)] = temp_combo;
12957 }
12958 }
12959 }
12960
12961 return 1;
12962 }
12963
12964 int32_t readcombofile(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t start)
12965 {
12966 dword section_version=0;
12967 int32_t zversion = 0;
12968 int32_t zbuild = 0;
12969
12970 if(!p_igetl(&zversion,f))
12971 {
12972 return 0;
12973 }
12974 if(!p_igetl(&zbuild,f))
12975 {
12976 return 0;
12977 }
12978 if(!p_igetw(&section_version,f))
12979 {
12980 return 0;
12981 }
12982 if(!read_deprecated_section_cversion(f))
12983 {
12984 return 0;
12985 }
12986
12987 if ( zversion > ZELDA_VERSION )
12988 {
12989 al_trace("Cannot read .zcombo packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
12990 return 0;
12991 }
12992
12993 else if ( ( section_version > V_COMBOS ))
12994 {
12995 al_trace("Cannot read .zcombo packfile made using V_COMBOS (%d)\n", section_version);
12996 return 0;
12997
12998 }
12999 else
13000 {
13001 al_trace("Reading a .zcombo packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13002 }
13003
13004 int32_t index = 0;
13005 int32_t count = 0;
13006
13007 //tile id
13008 if(!p_igetl(&index,f))
13009 {
13010 return 0;
13011 }
13012 if(start > -1) index = start;
13013
13014 //tile count
13015 if(!p_igetl(&count,f))
13016 {
13017 return 0;
13018 }
13019 reset_combo_animations();
13020 reset_combo_animations2();
13021
13022 if(section_version < 33)
13023 return readcombofile_old(f,skip,nooverwrite,zversion,section_version,index,count);
13024
13025 newcombo temp_combo;
13026 size_t end = index+count;
13027 for ( size_t q = index; q < end; q++ )
13028 {
13029 auto ret = readcombo_loop(f,section_version,temp_combo);
13030 if(ret) return 0;
13031
13032 if ( !(skip && q-1 < skip) )
13033 {
13034 if ( !nooverwrite || combobuf[q].is_blank() )
13035 {
13036 combobuf[q] = temp_combo;
13037 }
13038 }
13039 }
13040
13041 return 1;
13042 }
13043 int32_t readcombofile_to_location(PACKFILE *f, int32_t start, byte nooverwrite, int32_t skip)
13044 {
13045 return readcombofile(f,skip,nooverwrite,start);
13046 }
13047 int32_t writecombofile(PACKFILE *f, int32_t index, int32_t count)
13048 {
13049 dword section_version=V_COMBOS;
13050 int32_t zversion = ZELDA_VERSION;
13051 int32_t zbuild = VERSION_BUILD;
13052
13053 if(!p_iputl(zversion,f))
13054 {
13055 return 0;
13056 }
13057 if(!p_iputl(zbuild,f))
13058 {
13059 return 0;
13060 }
13061 if(!p_iputw(section_version,f))
13062 {
13063 return 0;
13064 }
13065
13066 if(!write_deprecated_section_cversion(section_version,f))
13067 {
13068 return 0;
13069 }
13070
13071 //start tile id
13072 if(!p_iputl(index,f))
13073 {
13074 return 0;
13075 }
13076
13077 //count
13078 if(!p_iputl(count,f))
13079 {
13080 return 0;
13081 }
13082 reset_combo_animations();
13083 reset_combo_animations2();
13084 size_t end = index+count;
13085 for(size_t q = index; q < end; ++q)
13086 {
13087 if(writecombo_loop(f, section_version, combobuf[q]))
13088 return 0;
13089 }
13090
13091 return 1;
13092
13093 }
13094
13095 //.ZALIAS
13096
13097
13098 //.ZALIAS
13099
13100 int32_t readcomboaliasfile(PACKFILE *f)
13101 {
13102 dword section_version=0;
13103 int32_t zversion = 0;
13104 int32_t zbuild = 0;
13105 word tempword = 0;
13106
13107 if(!p_igetl(&zversion,f))
13108 {
13109 return 0;
13110 }
13111 if(!p_igetl(&zbuild,f))
13112 {
13113 return 0;
13114 }
13115 if(!p_igetw(&section_version,f))
13116 {
13117 return 0;
13118 }
13119 if(!read_deprecated_section_cversion(f))
13120 {
13121 return 0;
13122 }
13123 al_trace("readoneweapon section_version: %d\n", section_version);
13124
13125 if ( zversion > ZELDA_VERSION )
13126 {
13127 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13128 return 0;
13129 }
13130
13131 else if ( ( section_version > V_COMBOALIASES ))
13132 {
13133 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d)\n", section_version);
13134 return 0;
13135
13136 }
13137 else
13138 {
13139 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13140 }
13141
13142 int32_t index = 0;
13143 int32_t count = 0;
13144 int32_t count2 = 0;
13145 byte tempcset = 0;
13146
13147 //tile id
13148 if(!p_igetl(&index,f))
13149 {
13150 return 0;
13151 }
13152 al_trace("Reading combo: index(%d)\n", index);
13153
13154 //tile count
13155 if(!p_igetl(&count,f))
13156 {
13157 return 0;
13158 }
13159 al_trace("Reading combo: count(%d)\n", count);
13160
13161 combo_alias temp_alias;
13162
13163 for ( int32_t tilect = 0; tilect < count; tilect++ )
13164 {
13165 temp_alias.clear();
13166 if(!p_igetw(&temp_alias.combo,f))
13167 {
13168 return 0;
13169 }
13170
13171 if(!p_getc(&temp_alias.cset,f))
13172 {
13173 return 0;
13174 }
13175
13176
13177
13178 if(!p_igetl(&count2,f))
13179 {
13180 return 0;
13181 }
13182 al_trace("Read, Combo alias count is: %d\n", count2);
13183 if(!p_getc(&temp_alias.width,f))
13184 {
13185 return 0;
13186 }
13187
13188 if(!p_getc(&temp_alias.height,f))
13189 {
13190 return 0;
13191 }
13192
13193 if(!p_getc(&temp_alias.layermask,f))
13194 {
13195 return 0;
13196 }
13197 //These values are flexible, and may differ in size, so we delete them
13198 //and recreate them at the correct size on the pointer.
13199 temp_alias.combos.clear();
13200 temp_alias.csets.clear();
13201 for(int32_t k=0; k<count2; k++)
13202 {
13203 if(!p_igetw(&tempword,f))
13204 {
13205 return 0;
13206 }
13207 else
13208 {
13209
13210
13211 temp_alias.combos[k] = tempword;
13212 }
13213 }
13214
13215 for(int32_t k=0; k<count2; k++)
13216 {
13217 if(!p_getc(&tempcset,f))
13218 //if(!p_getc(&temp_alias.csets[k],f))
13219 {
13220 return 0;
13221 }
13222 else
13223 {
13224
13225 temp_alias.csets[k] = tempcset;
13226 }
13227 }
13228 combo_aliases[index+(tilect)] = temp_alias;
13229 }
13230
13231 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
13232
13233
13234 return 1;
13235
13236 }
13237
13238 int32_t readcomboaliasfile_to_location(PACKFILE *f, int32_t start)
13239 {
13240 dword section_version=0;
13241 int32_t zversion = 0;
13242 int32_t zbuild = 0;
13243
13244 if(!p_igetl(&zversion,f))
13245 {
13246 return 0;
13247 }
13248 if(!p_igetl(&zbuild,f))
13249 {
13250 return 0;
13251 }
13252 if(!p_igetw(&section_version,f))
13253 {
13254 return 0;
13255 }
13256 if(!read_deprecated_section_cversion(f))
13257 {
13258 return 0;
13259 }
13260 al_trace("readcomboaliasfile_to_location section_version: %d\n", section_version);
13261
13262 if ( zversion > ZELDA_VERSION )
13263 {
13264 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13265 return 0;
13266 }
13267 else if ( ( section_version > V_COMBOALIASES ))
13268 {
13269 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d)\n", section_version);
13270 return 0;
13271
13272 }
13273 else
13274 {
13275 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13276 }
13277
13278 int32_t index = 0;
13279 int32_t count = 0;
13280 int32_t count2 = 0;
13281 byte tempcset = 0;
13282 word tempword = 0;
13283
13284
13285 //tile id
13286 if(!p_igetl(&index,f))
13287 {
13288 return 0;
13289 }
13290 al_trace("Reading tile: index(%d)\n", index);
13291
13292 //tile count
13293 if(!p_igetl(&count,f))
13294 {
13295 return 0;
13296 }
13297 al_trace("Reading tile: count(%d)\n", count);
13298
13299
13300 combo_alias temp_alias;
13301
13302 for ( int32_t tilect = 0; tilect < count; tilect++ )
13303 {
13304 temp_alias.clear();
13305 if(!p_igetw(&temp_alias.combo,f))
13306 {
13307 return 0;
13308 }
13309
13310 if(!p_getc(&temp_alias.cset,f))
13311 {
13312 return 0;
13313 }
13314
13315 int32_t count2 = 0;
13316
13317 if(!p_igetl(&count2,f))
13318 {
13319 return 0;
13320 }
13321
13322 if(!p_getc(&temp_alias.width,f))
13323 {
13324 return 0;
13325 }
13326
13327 if(!p_getc(&temp_alias.height,f))
13328 {
13329 return 0;
13330 }
13331
13332 if(!p_getc(&temp_alias.layermask,f))
13333 {
13334 return 0;
13335 }
13336 //These values are flexible, and may differ in size, so we delete them
13337 //and recreate them at the correct size on the pointer.
13338 temp_alias.combos.clear();
13339 temp_alias.csets.clear();
13340
13341 for(int32_t k=0; k<count2; k++)
13342 {
13343 if(!p_igetw(&tempword,f))
13344 {
13345 return 0;
13346 }
13347 else
13348 {
13349 temp_alias.combos[k] = tempword;
13350 }
13351 }
13352
13353 for(int32_t k=0; k<count2; k++)
13354 {
13355 if(!p_getc(&tempcset,f))
13356 {
13357 return 0;
13358 }
13359 else
13360 {
13361 temp_alias.csets[k] = tempcset;
13362 }
13363 }
13364
13365 if ( start+(tilect) < MAXCOMBOALIASES )
13366 {
13367 combo_aliases[start + (tilect)] = temp_alias;
13368 }
13369 }
13370 return 1;
13371 }
13372 int32_t writecomboaliasfile(PACKFILE *f, int32_t index, int32_t count)
13373 {
13374 al_trace("Running writecomboaliasfile\n");
13375 dword section_version=V_COMBOALIASES;
13376 int32_t zversion = ZELDA_VERSION;
13377 int32_t zbuild = VERSION_BUILD;
13378
13379 if(!p_iputl(zversion,f))
13380 {
13381 return 0;
13382 }
13383 if(!p_iputl(zbuild,f))
13384 {
13385 return 0;
13386 }
13387 if(!p_iputw(section_version,f))
13388 {
13389 return 0;
13390 }
13391
13392 if(!write_deprecated_section_cversion(section_version,f))
13393 {
13394 return 0;
13395 }
13396
13397 //start tile id
13398 if(!p_iputl(index,f))
13399 {
13400 return 0;
13401 }
13402
13403 //count
13404 if(!p_iputl(count,f))
13405 {
13406 return 0;
13407 }
13408
13409 for ( int32_t tilect = 0; tilect < count; tilect++ )
13410 {
13411
13412 if(!p_iputw(combo_aliases[index+(tilect)].combo,f))
13413 {
13414 return 0;
13415 }
13416
13417 if(!p_putc(combo_aliases[index+(tilect)].cset,f))
13418 {
13419 return 0;
13420 }
13421
13422 int32_t count2 = ((combo_aliases[index+(tilect)].width+1)*(combo_aliases[index+(tilect)].height+1))*(comboa_lmasktotal(combo_aliases[index+(tilect)].layermask)+1);
13423
13424 if(!p_iputl(count2,f))
13425 {
13426 return 0;
13427 }
13428 al_trace("Write`, Combo alias count is: %d\n", count2);
13429
13430 if(!p_putc(combo_aliases[index+(tilect)].width,f))
13431 {
13432 return 0;
13433 }
13434
13435 if(!p_putc(combo_aliases[index+(tilect)].height,f))
13436 {
13437 return 0;
13438 }
13439
13440 if(!p_putc(combo_aliases[index+(tilect)].layermask,f))
13441 {
13442 return 0;
13443 }
13444
13445 for(int32_t k=0; k<count2; k++)
13446 {
13447 if(!p_iputw(combo_aliases[index+(tilect)].combos[k],f))
13448 {
13449 return 0;
13450 }
13451 }
13452
13453 for(int32_t k=0; k<count2; k++)
13454 {
13455 if(!p_putc(combo_aliases[index+(tilect)].csets[k],f))
13456 {
13457 return 0;
13458 }
13459 }
13460 }
13461
13462 return 1;
13463
13464 }
13465